EMQX消息流入速率和流出速率异常

先查 stats.enable。它关闭时,clients list 和客户端详情里的 recv_msgsend_msginflight 会一直是初始值,但全局 broker metrics 仍然正常计数,这正好符合“所有客户端都是 0、全局流出却持续增长”的现象。

执行:

/usr/bin/emqx ctl conf show stats

如果输出是 enable = false,前面用 inflight=0 排除重传的结论就没有依据。即使为 true,5.5.0 的连接统计也是异步刷新的,默认可能滞后约 15 秒;这次两份客户端快照只隔了约 12.8 秒,也不足以排除重传。

这批全局指标仍然指向 QoS 1 未确认:

  • messages.qos1.sent 增加 15,495;
  • messages.ackedpackets.puback.received 都只增加 2;
  • messages.deliveredmessages.sent 同时增加 15,542。

也就是发出了约 1.55 万个 QoS 1 PUBLISH,只收到 2 个 PUBACK。EMQX 重传时 messages.delivered 也会增长,不能据此判断为纯订阅扇出。

先把 conf show stats 的完整输出贴出来。若统计已开启,下一次曲线上升时把采样窗口拉到 40 秒,覆盖一次默认 30 秒重传周期:

out="/tmp/emqx-flow-long-$(date +%Y%m%d-%H%M%S)"
mkdir -p "$out"

for i in 1 2 3; do
  date -Ins > "$out/time.$i.txt"
  /usr/bin/emqx ctl broker metrics > "$out/metrics.$i.txt"
  /usr/bin/emqx ctl clients list | sort > "$out/clients.$i.txt"
  [ "$i" = 3 ] || sleep 20
done

diff -u "$out/metrics.1.txt" "$out/metrics.3.txt" > "$out/metrics.diff.txt" || true
diff -u "$out/clients.1.txt" "$out/clients.3.txt" > "$out/clients.diff.txt" || true

tar -czf "$out.tgz" -C "$(dirname "$out")" "$(basename "$out")"
echo "$out.tgz"

你贴的单客户端页面只显示 8 个接收 TCP 报文、1 个流入 PUBLISH,说明那个连接本身不是当前主要收发对象。新的 clients.diff.txt 重点看哪些客户端的 delivered_msgsinflight 在增长;这才能定位是哪批订阅端没有回 PUBACK。

image

还有一个当前告警,查询客户端ID和IP都没有找到

这个 conn_congestion 告警:当时有一个订阅端的 TCP 发送队列排不出去
告警里的关键数据:

  • Client ID:paho29575014931761269
  • send_pend=23573,说明 socket 仍有待发送数据;
  • send_cnt=294722send_oct=3234916133,EMQX 已向它发送约 3.23 GB;
  • recv_cnt=126recv_oct=441,它基本上只接收消息。

这和前面“QoS 1 大量发送、PUBACK 极少”的窗口能对上。先把这个 Paho 客户端当作慢订阅端排查:它是否停止消费、网络是否限速、进程是否卡住,以及订阅了哪些主题。

conf show stats 返回 stats {} 表示没有显式覆盖配置;5.5.0 的默认值是 stats.enable=true,不是关闭统计。

现在按 Client ID 和 IP 查不到,说明这条连接已经断开,或者 Paho 重连时生成了新的 Client ID。正常断开后拥塞告警应转入历史告警;如果刷新后它仍留在“当前告警”,那是残留告警,不代表旧连接仍在线,但告警中记录的拥塞现场仍然有效。

先查这个 Client ID 在告警时段的连接和断开日志:

clientid='paho29575014931761269'

grep -R -n -- "$clientid" /var/log/emqx /opt/emqx/log 2>/dev/null | tail -100

journalctl -u emqx \
  --since '2026-07-23 09:50:00' \
  --until '2026-07-23 10:50:00' \
  --no-pager | grep -- "$clientid"

下次出现同类告警时,不要等连接消失,马上执行:

/usr/bin/emqx ctl clients show '<告警中的 Client ID>'
/usr/bin/emqx ctl subscriptions show '<告警中的 Client ID>'

把匹配到的日志和订阅贴出来。现在应沿着这个慢订阅端查,不需要继续猜全局计数 Bug。

现在emqx上还是显示为当前告警,查找不到的