channel_closed 想确认该日志含义及根因定位方法

我在 EMQX 日志中看到如下 error 日志,想确认一下该日志的具体含义,以及应该如何进一步定位根因。
日志如下:
{
“time”: 1779107976312384,
“level”: “error”,
“msg”: “message=channel_closed driver=tcp socket="#Port<0.164581>" action=stopping”,
“pid”: “<0.5763482.0>”
}

  • EMQX 版本:5.8.4

这条日志表示一个 TCP channel 被动关闭了,EMQX 随后把该 channel 进程停掉(action=stopping)。
socket="#Port<...>" 是 Erlang 运行时内部的 socket ,,单看这一条没法直接定位根因。
不过。常见两类原因:

  • 集群场景:节点间 gen_rpc/Mria 通道被对端拒绝或网络抖动后关闭。
  • 客户端场景:客户端主动断开、网络中断、keepalive 超时导致 TCP 关闭。
    要继续定位,贴同一时间窗口(前后 30~60 秒)的完整日志,重点看这些关键词:
  • connect_to_remote_server
  • gen_rpc / mria / partition
  • econnrefused / econnreset / tcp_closed

如果怀疑是客户端侧,贴对应 clientid 的 emqx_connection_terminated 日志
把关联日志贴出来,基本就能把原因定到网络/对端拒绝/客户端断开这三类里。

05/18 20:39:38.390263

{"time":1779107977723540,"level":"info","msg":"Mria(Membership): Node emqx@10.xxxxxx down","domain":["mria","membership"],"pid":"<0.3599.0>"}

05/18 20:39:37.389310

{"time":1779107976324278,"level":"error","msg":"message=channel_closed driver=tcp socket=\"#Port<0.73>\" action=stopping","pid":"<0.5176.0>"}

05/18 20:39:26.381000

{"time":1779107966193138,"level":"info","msg":"event=initializing_client driver=tcp node=\"emqx@10.xxxxxxx\" port=5369","pid":"<0.5929.0>"}

感觉是集群中的场景,出现了集群场景的tcp channel报错,会影响什么呢。

这是集群节点间的 RPC/Mria 通道断开。Node emqx@... down 已经说明对端节点在该时刻被判定离线,channel_closed 是后续清理动作。
会有的影响主要是这段离线窗口:

  • 与该节点相关的跨节点路由/会话同步会中断,得=重连恢复。
  • 连在故障节点上的客户端会断开并重连;连在其他健康节点上的客户端通常可继续收发。
  • 如果频繁抖动,会出现集群拓扑反复变化,表现为转发时延抖动、短时投递失败重试。

  1. 在各节点执行 emqx ctl cluster status --json,看 stopped_nodes 是否持续出现同一节点。
  2. 检查节点间 5369 端口链路(防火墙/NAT/安全组),确认没有间歇性拒绝或重置。
  3. 拉同一时间窗日志关键词:connect_to_remote_servereconnrefusedeconnresetmriagen_rpc

日志显示的节点,经过蓝绿部署后已经下线了,为什么emqx还在往已经下线的老节点同步呢

这是预期行为:老节点虽然下线了,但还在集群成员或发现源里,存活节点会继续尝试连它的 5369,所以你会看到 initializing_client + channel_closed
先按这三步处理:

  1. 在任一存活节点执行 emqx ctl cluster status --json,确认旧节点是否在 stopped_nodes
  2. 如果在,执行 emqx ctl cluster force-leave emqx@旧节点名,再查一次 cluster status,确保它已经被移除。
  3. 清理发现源里的旧节点:
    • static:从 cluster.static.seeds 删除旧节点并滚动重启;
    • dns / k8s:删除旧 IP / endpoint,确认解析结果里不再有它。
      补充一个点:cluster.autoclean 默认是 24h,不手动 force-leave 的话,这段时间里重连日志会反复出现。