ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

EMQX 插件集群配置拉取告警日志降噪实践:基于 PR 16842 的修复原理与源码解析

EMQX 插件集群配置拉取告警日志降噪实践:基于 PR 16842 的修复原理与源码解析 后端物联网消息队列通信【免费下载链接】emqxThe most scalable and reliable MQTT broker for AI, IoT, IIoT and connected vehicles项目地址https://gitcode.com/gh_mirrors/em/emqx点击查看免费下载导读EMQX 在集群启动或安装插件时节点需要从对端节点peer node拉取插件的本地配置以保证集群内所有节点配置一致。在旧版本中即使所有对端节点都尚未持有该插件配置例如该插件是集群中第一个被加载的当前节点也会打印一条 warning 级别日志在大型集群中会形成大量噪音干扰真实故障的排查。本文基于 EMQX 6.2.0 变更说明 changes/ee/fix-16842.en.md对应 PR #16842收录于 changes/6.2.0.en.md 的 Plugins 小节结合 emqx_plugins 应用源码与测试用例完整讲解该问题的产生背景、修复方案、底层调用链与验证方式。读完本文你将掌握 EMQX 插件配置在集群中的同步机制以及如何区分良性缺失与真实故障两类日志并能依据源码理解其日志分级策略。一、问题背景节点启动时为何要从对端节点拉取插件配置EMQX 的插件机制支持两种配置文件来源插件随包自带的默认配置vendored with the plugin以及从其他节点获取的、已经过插件校验的配置fetched from another node。当某个节点首次加载插件、或本地配置目录尚未就绪时它需要向集群中的其他运行节点发起 RPC 调用尝试获取该插件的配置快照以保证与集群现有状态一致。从源码 emqx_plugins.erl 可以看到完整的决策流程ensure_local_config(NameVsn, Mode) - case emqx_plugins_fs:ensure_config_dir(NameVsn) of ok - %% get config from other nodes or get from tarball do_ensure_local_config(NameVsn, Mode); {error, _} Error - ?SLOG(warning, #{ msg failed_to_ensure_config_dir, name_vsn NameVsn, reason Error }), Error end. do_ensure_local_config(NameVsn, ?fresh_install) - emqx_plugins_local_config:copy_default(NameVsn); do_ensure_local_config(NameVsn, ?normal) - case peer_nodes() of [] - emqx_plugins_local_config:copy_default(NameVsn); Nodes - case get_config_from_any_node(Nodes, NameVsn, []) of {ok, Config} when is_map(Config) - emqx_plugins_local_config:update(NameVsn, Config); {error, Errors} - log_config_not_found(NameVsn, Errors), emqx_plugins_local_config:copy_default(NameVsn) end end.关键逻辑要点全新安装?fresh_install直接拷贝插件自带的默认配置不访问任何对端节点正常启动?normal先通过peer_nodes()获取当前集群中除本节点以外的运行节点列表其实现为[N || N - mria:running_nodes(), N / node()]见 emqx_plugins.erl若集群中只有本节点Nodes []同样直接拷贝默认配置无需网络交互若存在其他节点则依次向各节点发起 RPC 尝试获取配置成功则用集群配置覆盖本地全部失败则回退到默认配置并调用log_config_not_found/2记录日志。二、RPC 调用链如何向对端节点请求插件配置get_config_from_any_node/3是逐节点尝试的核心实现见 emqx_plugins.erlget_config_from_any_node([], _NameVsn, Errors) - {error, Errors}; get_config_from_any_node([Node | RestNodes], NameVsn, Errors) - case emqx_plugins_proto_v2:get_config( Node, NameVsn, ?CONFIG_FORMAT_MAP, ?plugin_conf_not_found, 5_000 ) of {ok, ?plugin_conf_not_found} - get_config_from_any_node(RestNodes, NameVsn, [{Node, config_not_found} | Errors]); {ok, _} Res - ?SLOG(debug, #{ msg get_plugin_config_from_cluster_successfully, node Node, name_vsn NameVsn }), Res; Err - get_config_from_any_node(RestNodes, NameVsn, [{Node, Err} | Errors]) end.这段代码清晰地区分了三种 RPC 结果{ok, ?plugin_conf_not_found}对端节点正常响应但明确表示我没有这个插件的配置。这是良性场景记录为{Node, config_not_found}后继续尝试下一个节点{ok, _}成功拿到配置记录一条 debug 日志get_plugin_config_from_cluster_successfully并直接返回其他错误ErrRPC 调用本身失败如节点不可达、超时、协议异常记录{Node, Err}后继续尝试下一个节点。注意 RPC 调用通过 emqx_plugins_proto_v2 完成仓库中同时维护了 v2/v3/v4/v5 多个协议版本见 proto 目录单次调用超时时间固定为5_000毫秒配置格式为?CONFIG_FORMAT_MAP。只有当所有节点都尝试完毕后仍未成功get_config_from_any_node才会返回{error, Errors}把收集到的错误列表交还给调用方。三、修复核心按错误类型区分日志级别修复前的问题在于无论错误列表里全是config_not_found良性还是混入了 RPC 失败/超时真实故障最终都会统一打印 warning 日志。修复后的log_config_not_found/2见 emqx_plugins.erl会先对错误列表做一次分类判断log_config_not_found(NameVsn, Errors) - case is_all_config_not_found(Errors) of true - ?SLOG(debug, #{ msg plugin_config_not_found_in_cluster, name_vsn NameVsn, hint This is expected when this plugin has not been started in the cluster before }); false - ?SLOG(warning, #{ msg failed_to_get_plugin_config_from_cluster, name_vsn NameVsn, reason Errors }) end.分类器is_all_config_not_found/1见 emqx_plugins.erl的实现非常直观is_all_config_not_found([]) - true; is_all_config_not_found([{_Node, config_not_found} | Rest]) - is_all_config_not_found(Rest); is_all_config_not_found([_ | _]) - false.即空列表理论上不会出现或错误列表中的每一项都是{Node, config_not_found}时返回true否则一旦混入任何其他错误RPC 失败、超时、未知异常就返回false。由此形成清晰的分级策略场景判断依据日志级别日志消息所有对端节点都没有该插件配置集群首次加载插件is_all_config_not_found(Errors) : truedebugplugin_config_not_found_in_cluster至少一个节点返回 RPC 失败、超时等真实错误is_all_config_not_found(Errors) : falsewarningfailed_to_get_plugin_config_from_cluster其中良性场景还会附带一条hint字段This is expected when this plugin has not been started in the cluster before帮助阅读 debug 日志的人理解这是预期行为。无论哪种情况配置缺失的最终兜底策略不变——回退到插件自带的默认配置emqx_plugins_local_config:copy_default(NameVsn)保证插件可以正常启动。四、测试验证集群场景下的行为断言该修复配套了对应的测试用例t_fresh_install_skips_peer_config见 emqx_plugins_SUITE.erlt_fresh_install_skips_peer_config(_Config) - #{name_vsn : NameVsn} get_demo_plugin_package(), ?check_trace( emqx_plugins:ensure_installed(NameVsn, ?fresh_install), fun(Trace) - ?assertMatch( [], ?of_kind(failed_to_get_plugin_config_from_cluster, Trace) ), ok end ), ok emqx_plugins:ensure_uninstalled(NameVsn), ok.该用例在集群环境下以?fresh_install模式安装一个 demo 插件包并通过?check_trace收集运行期产生的全部日志追踪断言其中不存在failed_to_get_plugin_config_from_cluster这条 warning 消息。这直接印证了修复目标在没有任何对端节点持有该插件配置的良性场景下不再产生告警级日志。测试中还使用了配套的 demo 插件包get_demo_plugin_package/0并覆盖了安装、描述describe与卸载ensure_uninstalled的完整生命周期。同一测试文件中还包含t_install_package_rpc等用例共同保障插件集群安装路径的稳定性。五、运维视角如何利用日志分级快速定位问题修复生效后运维与开发人员在排查 EMQX 集群插件问题时可以参考以下日志分布debug 级别的plugin_config_not_found_in_cluster属于正常启动流程表明当前节点是集群中第一个加载该插件的节点或对端节点尚未同步该插件配置无需处理warning 级别的failed_to_get_plugin_config_from_cluster说明至少有一个对端节点在 RPC 调用上出现了真实异常reason字段会携带具体错误如timeout、nodedown、连接拒绝等此时应检查对应节点的运行状态、mria:running_nodes()所见集群成员以及节点间网络连通性debug 级别的get_plugin_config_from_cluster_successfully表示从指定节点成功获取配置可用于确认配置同步来源。从更广的视角看插件配置同步只是 EMQX 集群配置一致性机制的一部分本地配置要么来自插件自带的默认配置要么来自其他已经过插件校验的节点因此在两种来源下notify_config_change回调都会执行但不期望插件拒绝这类配置见 emqx_plugins.erl 中的注释说明。六、小结PR #16842 是对 EMQX 插件集群配置同步路径上一次小而精准的日志治理优化根因节点启动时向对端节点批量拉取插件配置所有对端均无此配置的良性场景被误报为 warning污染日志方案通过is_all_config_not_found/1分类错误列表——全为config_not_found时降级为 debug 日志并附解释 hint混入 RPC 失败/超时等真实错误时保留 warning 级别验证测试用例t_fresh_install_skips_peer_config在集群 trace 中断言不再出现failed_to_get_plugin_config_from_cluster告警收益日志噪音显著下降真实故障RPC 失败、超时的可观测性反而更强。该变更随 EMQX 6.2.0 发布相关源码位于 apps/emqx_plugins/src/emqx_plugins.erl测试覆盖见 apps/emqx_plugins/test/emqx_plugins_SUITE.erl变更说明见 changes/6.2.0.en.md。对于运行多节点集群并大量使用插件的用户升级到包含该修复的版本即可自动享受更干净的插件相关日志。赞分享后端物联网消息队列通信【免费下载链接】emqxThe most scalable and reliable MQTT broker for AI, IoT, IIoT and connected vehicles项目地址https://gitcode.com/gh_mirrors/em/emqx点击查看免费下载相关推荐EMQX 集群安全配置一致性监控security_profile_divergence 告警原理与滚动升级实践EMQX 集群安全配置一致性监控 security_profile_divergence 告警原理与滚动升级实践 EMQX 从 7.0 起引入节点级安全配置后端物联网消息队列通信EMQX 消除 MQTT v5 CONNACK 拒绝连接后的 unclean_terminate 误报警告日志PR 15872 修复解析EMQX 消除 MQTT v5 CONNACK 拒绝连接后的 unclean_terminate 误报警告日志PR 15872 修复解析 导读 本文围绕 E后端物联网消息队列通信EMQX Kafka 数据集成日志修复解析 not_all_kafka_partitions_connected 健康检查告警的日志详情增强EMQX Kafka 数据集成日志修复解析 not_all_kafka_partitions_connected 健康检查告警的日志详情增强 本篇文章聚焦后端物联网消息队列通信创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表