启动的mqtt客户端订阅设备上报的数据,比如刚开始订阅10个topic,运行着一段时间,topic会主动掉,变成5个,是什么原因导致的
麻烦补下这几项关键信息:
- 这类现象一般都是会话被重建:给下 EMQX 版本和部署方式(Docker/K8s/裸机)。
- 客户端连接参数贴一下:MQTT 协议版本、clean_start/clean_session、session_expiry_interval。
- 确认是否有多个进程共用同一个 clientid;有的话会发生 takenover/discarded,订阅会看起来“变少”。
- 把问题出现时这两个输出贴出来:emqx ctl clients show ;emqx ctl topics list | grep <clientid 或关键topic>。
- 再贴一段 broker 日志(掉订阅前后 1-2 分钟),重点看 keepalive_timeout、takenover、discarded、not_authorized。
现在的现象是跑着跑着mqtt客户端订阅的topic掉了,重启重新订阅上
现在的现象是跑着跑着mqtt客户端订阅的topic掉了,重启重新订阅上;
没有多个进程共用同一个 clientid
来点有用的日志
3、4比较难,之前日志没有映射出来
你这类“跑一段时间订阅变少”,从你截图看最可疑的是会话参数组合。Clean Start=false 但 Session Expiry Interval=0,一旦连接有抖动并重连,会话会被立即回收,之前订阅不会保留;再叠加 Keepalive=15(超时阈值约 22.5s),网络稍有抖动就容易触发断连重连。
先改这 3 个点再观察:
- 客户端把
session_expiry_interval改成非 0(先用3600或86400)。 keepalive先提高到60(至少别用 15)。- 客户端每次重连后都执行完整订阅,并检查每条
SUBACK返回码。
你说 3、4 不方便拿日志,那就先用这 3 条命令,不需要映射容器日志目录:
docker exec -it <emqx容器名> emqx ctl listeners
docker exec -it <emqx容器名> emqx ctl clients show mqtt_21944
docker logs --since 30m <emqx容器名> | grep -E "mqtt_21944|keepalive_timeout|takenover|discarded|tcp_closed|not_authorized"
重点看两个东西:
shutdown_count里有没有持续增长的keepalive_timeout/tcp_closed/takenover- 断连时间点是否和“订阅变少”的时间点一致
另外你截图里看起来有两个相近 clientid 在线(mqtt_21944和mqtt_21944_pro...),确认下是不是同一业务逻辑创建了两个连接,避免把订阅分散到不同连接上。
把这三条命令输出贴上来。
root@localhost ~]# docker exec -it emqx emqx ctl listeners
ssl:default
listen_on : 0.0.0.0:8883
acceptors : 16
proxy_protocol : false
running : true
current_conn : 0
max_conns : 512000
tcp:default
listen_on : 0.0.0.0:1883
acceptors : 1024
proxy_protocol : false
running : true
current_conn : 1139
max_conns : 1024000
ws:default
listen_on : 0.0.0.0:8083
acceptors : 16
proxy_protocol : false
running : true
ws:default
listen_on : 0.0.0.0:8083
acceptors : 16
proxy_protocol : false
running : true
current_conn : 0
max_conns : 1024000
wss:default
listen_on : 0.0.0.0:8084
acceptors : 16
proxy_protocol : false
running : true
current_conn : 0
max_conns : 512000
[root@localhost ~]# docker exec -it emqx emqx ctl clients show mqtt_90973
Client(mqtt_90973, username=root, peername=172.19.4.23:50842, clean_start=false, keepalive=15, session_expiry_interval=0, subscriptions=40, inflight=0, awaiting_rel=0, delivered_msgs=390286, enqueued_msgs=0, dropped_msgs=0, connected=true, created_at=1775009009663, connected_at=1775009009663)
[root@localhost ~]# docker logs --since 30m emqx | grep -E “mqtt_90973|keepalive_timeout|takenover|discarded|tcp_closed|not_authorized”
[root@localhost ~]#
问题不是 Broker 主动“丢订阅”,而是会话配置会导致“断线即丢会话”:clean_start=false + session_expiry_interval=0 + keepalive=15。
你贴的 emqx ctl clients show mqtt_90973 里 subscriptions=40,说明当前这条连接在 Broker 侧订阅还在。你看到“10 变 5”更像是客户端重连后本地订阅状态/统计逻辑没恢复,或者短暂断连后没有重新订阅成功。
先改这 3 个参数再跑 24h:
clean_start=false
session_expiry_interval=86400
keepalive=60
把观察窗口拉长:
docker logs --since 6h emqx 2>&1 | grep -E 'mqtt_90973|keepalive_timeout|takenover|discarded|tcp_closed|not_authorized'
异常时刻再连跑两条:
docker exec -it emqx emqx ctl clients show mqtt_90973
docker exec -it emqx emqx ctl clients show mqtt_90973 | grep shutdown_count
会话过期间隔为 0 时,客户端一断开会话和订阅会立即丢弃;keepalive_timeout / tcp_closed / takenover 是定位断连原因的关键字段。
再贴一段客户端重连后的 SUBSCRIBE/SUBACK 日志(至少 3~5 条主题),需要排除是不是在重连阶段就有部分订阅返回失败。
好的,感谢

