后端物联网消息队列通信【免费下载链接】emqxThe most scalable and reliable MQTT broker for AI, IoT, IIoT and connected vehicles项目地址https://gitcode.com/gh_mirrors/em/emqx点击查看免费下载导读本文围绕 EMQX 官方变更记录 fix-16453.en.md 展开深入解析 EMQX 将分布式 RPC 底层库gen_rpc升级至 3.5.1 后如何解决集群中对端节点不可达时产生的 crash 日志长尾long tail、日志可读性差以及failed_to_connect_server高频刷屏三大运维痛点。读完本文你将理解 gen_rpc 在 EMQX 集群通信中的定位、日志回调机制的源码实现以及rpc.connect_timeout等关键配置对集群故障行为的影响。一、变更背景一次聚焦 RPC 日志体验的版本升级在 EMQX 5.x/6.x 的分布式架构中节点间通过gen_rpc库进行远程过程调用RPC用于路由同步、会话管理、配置分发等高频操作。变更记录 fix-16453.en.md 的核心内容如下将gen_rpc升级到3.5.1升级前当对端节点不可达时EMQX 可能因连接超时connect timeout产生长尾的 crash 日志long tail of crash logs新版本不再产生长尾并将 crash 日志转换为更可读的error日志高频出现的failed_to_connect_server日志被限流throttled避免刷屏。这是一个典型的小版本升级 日志回调改造组合既要靠上游库修复崩溃报告生成逻辑也要在 EMQX 侧配套实现日志过滤与限流才能达成最终效果。二、gen_rpc 在 EMQX 中的角色与依赖锁定gen_rpc是 EMQX 维护的 Erlang/OTP 分布式 RPC 库基于 TCP/SSL 的长连接池取代了 OTP 自带的rpc模块以实现更高的并发与可控性。从仓库证据看在 apps/emqx/mix.exs 中gen_rpc被声明为emqx应用的直接依赖在仓库根 mix.exs 中版本被统一锁定并强制覆盖def common_dep(:gen_rpc), do: {:gen_rpc, github: emqx/gen_rpc, tag: 3.5.1, override: true}即本次变更所升级的版本正是3.5.1且通过override: true保证全仓库所有子应用统一使用该版本避免依赖冲突导致部分模块仍跑在旧版行为上。EMQX 对 gen_rpc 的调用统一封装在 apps/emqx/src/emqx_rpc.erl 中提供call/4-6、cast/4-5、multicall/4-5等 API并做了两类关键处理客户端连接池化rpc_node/1根据rand:uniform/1或erlang:phash2/2在多个客户端连接间分发请求连接数量由配置rpc.client_num控制默认 10错误归一化maybe_badrpc/1将 gen_rpc 返回的{badrpc, Reason}/{badtcp, Reason}统一包装为{badrpc, Reason}供上层业务判断节点失败而非业务异常。当对端节点宕机或网络分区时这些调用就会触发连接建立失败进而产生变更记录中描述的日志问题。三、问题剖析连接超时为何会产生 crash 日志长尾在升级前的旧版 gen_rpc 中如果集群中存在一个无法路由的节点例如 IP 变更、节点彻底下线但集群成员信息尚未清理、或网络分区每次尝试建立 RPC 连接超时客户端进程都会生成一条crash report。由于 EMQX 集群中多个后台任务mria 消息复制、ekka 集群心跳、路由表同步等会周期性、多路并发地对各节点发起 RPC故障期间这些失败会在短时间内大量堆积形成长尾效应超时回调在较长时间窗口内反复触发日志在故障恢复后仍持续输出形成拖尾可读性差crash report 通常包含冗长的进程栈与状态转储堆栈噪声大不利于快速定位对端节点不可达这一根因刷屏failed_to_connect_server这类错误日志在故障持续期间以极高频率重复出现淹没其他重要日志增加日志存储成本并拖慢排障。四、解决方案一升级 gen_rpc 3.5.1 消除长尾上游 gen_rpc 3.5.1 修复了连接超时场景下的崩溃报告生成逻辑不再在每次失败时向 error_logger / SASL 报告注入 crash 事件从根本上消除了 crash 日志长尾。同时新版本引入了logger callback 机制gen_rpc:set_logger/1允许宿主应用接管 gen_rpc 内部的日志输出将原本以 crash report 形式呈现的信息改写为结构化、可读的error日志。这也解释了为何 EMQX 侧需要新增配套模块——见下一节。五、解决方案二EMQX 侧日志回调与限流实现1. 新增emqx_rpc_log日志回调模块为了配合 gen_rpc 3.5.1 的新接口EMQX 新增了模块 apps/emqx/src/emqx_rpc_log.erl其模块注释明确写道-module(emqx_rpc_log). -moduledoc Log callback for gen_rpc 3.5 or newer. Throttle the log message failed_to_connect_server. .该模块导出了两个函数init() - gen_rpc:set_logger(?MODULE). log(Level, Type, Msg, Data) - case Msg of failed_to_connect_server - ?SLOG_THROTTLE(Level, Data#{msg failed_to_connect_server}, ?META(Type)); _ - ?SLOG(Level, Data#{msg Msg}, ?META(Type)) end.其中?META(TYPE)定义为#{tag RPC, domain [gen_rpc, TYPE]}使所有 gen_rpc 日志带上RPC标签和[gen_rpc, ...]域便于日志检索与过滤。关键设计有两处消息归一化将字符串消息failed_to_connect_server转为原子failed_to_connect_server写入msg字段。这是 EMQX 日志限流机制的前提——日志系统按原子消息类型识别可限流的消息限流分支命中该消息时使用?SLOG_THROTTLE宏其余消息走普通?SLOG保证只对高频连接失败消息做节流不影响其他日志的实时性。2. 启动序列中的注册回调模块需要在 EMQX 应用启动时完成注册。apps/emqx/src/emqx_app.erl 的start/2中在配置加载、监听器启动之后调用emqx_rpc_log:init(),即gen_rpc:set_logger(emqx_rpc_log)此后 gen_rpc 3.5.1 的所有日志输出都会流经该回调。3. 限流的底层机制?SLOG_THROTTLE宏限流宏定义在 apps/emqx/include/logger.hrl-define(SLOG_THROTTLE(Level, Data, Meta), case logger:allow(Level, ?MODULE) of true - (fun(#{msg : __Msg} __Data) - case emqx_log_throttler:allow(__Msg, UniqueKey) of true - logger:log(Level, __Data, Meta); false - ?_DO_TRACE(maps:get(tag, Meta, Level), __Msg, maps:merge(__Data, Meta)) end end)(Data); false - ok end ).执行流程为先通过logger:allow/2判断该级别是否被启用未启用直接丢弃调用emqx_log_throttler:allow(Msg, UniqueKey)做限流判断——放行则正常写日志被限流则降级为 trace 记录?_DO_TRACE既压住了刷屏又不丢失诊断信息因此failed_to_connect_server在节点持续不可达期间只会在每个限流窗口输出有限条数其余被吞并的实例转入 trace 级别便于需要时再查。4. 与全局日志限流配置的联动该消息还出现在 EMQX 全局日志限流消息清单中。apps/emqx_conf/src/emqx_conf_schema.erl 的log.throttling.msgs默认值列表包含failed_to_connect_server这意味着运维人员可以通过配置调整其限流策略而不仅是依赖代码里的默认行为。同时 logger.hrl 中的注释也提醒使用?SLOG_THROTTLE的 msg 必须登记到log.throttling.msgs默认值列表——failed_to_connect_server正是遵循了这一约束。六、相关配置rpc 连接行为的关键旋钮本次变更的故障场景连接超时与 EMQX 的rpc配置段直接相关其 schema 定义于 apps/emqx_conf/src/emqx_conf_schema.erl。以下配置项对理解故障行为最为关键配置项类型默认值说明rpc.modesync/asyncasyncRPC 调用模式rpc.protocoltcp/ssltcpRPC 传输协议映射到gen_rpc.driverrpc.connect_timeoutduration5sRPC 连接超时映射到gen_rpc.connect_timeout故障场景下的超时行为由此控制rpc.client_num125610每个节点建立的 RPC 客户端连接数rpc.server_portpos_integer?DEFAULT_RPC_PORTRPC 服务监听端口rpc.async_batch_sizeinteger256异步调用批处理大小映射到gen_rpc.max_batch_sizerpc.port_discoverymanual/statelessstateless端口发现方式映射到gen_rpc.port_discovery在 etc 配置文件中可这样调整连接超时以配合故障演练或缩短不可达节点的失败反馈时间rpc { connect_timeout 5s client_num 10 }值得说明的是connect_timeout决定单次连接失败前等待多久超时后由 gen_rpc 3.5.1 输出归一化 error 日志并经emqx_rpc_log限流。升级后的行为是——故障期间日志量受控、日志格式稳定、故障恢复后无长尾残留。七、如何验证升级效果仓库中已有相关测试与工具可佐证升级后的行为单元测试覆盖错误归一化apps/emqx/src/emqx_rpc.erl 中的 eunit 测试覆盖了throw、error、exit、timeout、noconnection五类 RPC 失败结果其中noconnection用例直接针对节点不可达场景断言返回{badrpc, nxdomain}验证了升级后错误仍被正确封装为业务可识别的badrpc日志格式化兼容性测试apps/emqx/test/emqx_logger_fmt_SUITE.erl 模拟 gen_rpc 的{report, #{error transmission_failed, ...}}错误报告验证 text/json 两种日志格式化器不会因 gen_rpc 的报错结构而崩溃并断言输出中包含gen_rpc_error关键字集群测试基建apps/emqx/test/emqx_cth_cluster.erl 在测试集群的应用列表中显式包含gen_rpc确保测试环境与生产一致的 RPC 行为。运维侧验证手段模拟节点不可达如firewall断连或直接停止对端节点观察log/目录或emqx ctl log输出——升级后应看到的是带RPC标签的error日志且频率受控而非成片的 crash report。八、同类变更的一致性该修复并非孤立存在在仓库多个版本的变更记录中均有对应描述changes/6.0.2.en.md与本文相同的 gen_rpc 升级说明changes/6.1.0.en.md 与 changes/6.1.1.en.md沿用相同描述changes/ee/fix-16465.en.md企业版另一条关联变更同样提及failed_to_connect_server限流。这说明该修复被同步回多个维护分支属于影响面较广的集群稳定性改进。小结本次gen_rpc 3.5.1升级从三个层面解决了节点不可达场景下的日志体验问题上游库消除 crash 长尾、新增 logger callback 将崩溃报告转为可读 error 日志、EMQX 侧emqx_rpc_log配合?SLOG_THROTTLE限流抑制failed_to_connect_server刷屏。三者缺一不可共同提升了大规模集群在网络抖动、节点故障场景下的可观测性与可维护性。赞分享后端物联网消息队列通信【免费下载链接】emqxThe most scalable and reliable MQTT broker for AI, IoT, IIoT and connected vehicles项目地址https://gitcode.com/gh_mirrors/em/emqx点击查看免费下载相关推荐EMQX 集群 RPC 日志治理gen_rpc 3.5.1 升级与连接超时日志节流深度解析EMQX 集群 RPC 日志治理gen_rpc 3.5.1 升级与连接超时日志节流深度解析 导读 当集群中某个节点不可达时EMQX 节点间的 RPC远程过后端物联网消息队列通信EMQX CRL 缓存刷新失败自动驱逐机制从日志刷屏到优雅降级EMQX CRL 缓存刷新失败自动驱逐机制从日志刷屏到优雅降级 导读 本文围绕 EMQX 仓库中的变更记录 changes/ee/fix 15159.en.m后端物联网消息队列通信LocalSend零网络依赖跨设备文件传输的革命性解决方案LocalSend零网络依赖跨设备文件传输的革命性解决方案 你是否曾在不同设备间传输文件时感到头疼Windows到Android、macOS到iOS、甚至即时通讯网络/通信创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考