无人售货机靠 MQTT 协议和后台保持长连接,但掉线、重连失败、消息堆积是三个高频故障。本文从连接建立、心跳机制、QoS 等级三个维度,手把手教你排查和解决 MQTT 通讯问题,让设备稳定在线。

一、背景与痛点

智能售货机物联网方案的团队,十个里有八个被 MQTT 通讯折腾过。

典型症状包括:

  • 设备明明能联网,但后台显示离线
  • 消息发了但对方收不到,怀疑网络丢包
  • 设备在 4G 信号差的地方直接失联,怎么都重连不上

本文把常见问题归类为三类,分别给出解决方案。


二、核心内容

问题一:设备频繁掉线——心跳间隔没设对

MQTT 协议靠心跳(PINGREQ/PINGRESP)保活。如果心跳间隔和服务器要求不一致,服务器会主动断开连接。

常见误区:很多人在嵌入式设备上把心跳间隔设为 60 秒或更长,以为省电。但大多数 MQTT Broker(如 EMQ、Apollo)默认的连接超时是 60 秒,心跳间隔超过这个值就会被判定为死连接。

推荐配置

  • 心跳间隔设为 30 秒(服务器超时时间的一半,留足余量)
  • 如果设备用电池供电,可以在检测到低电量时临时延长到 60 秒,但恢复后要立即改回 30 秒

实测:心跳间隔从 60 秒调整到 30 秒后,某型号设备日均掉线次数从 47 次降到了 3 次。


问题二:重连逻辑有 Bug——退避策略做对了吗?

设备断线后,很多人的代码是"等待 1 秒,重连;再失败,等待 2 秒",但没有上限。问题是:在网络持续异常时,频繁重连会快速耗光设备电量,还可能被服务器识别为恶意请求,触发 IP 封禁

正确的退避策略

  • 首次重连等待 1 秒
  • 失败后指数退避:2 秒、4 秒、8 秒、16 秒……上限 5 分钟
  • 连续失败 10 次后,停止自动重连,标记设备状态为"需人工干预",并上报后台

同时要避免在设备重启时立即发起重连——建议加一个随机抖动(0~2 秒),防止大量设备同时上线造成服务器拥塞。


问题三:QoS 等级选错——消息到底有没有送达?

MQTT 有三个 QoS 等级,但很多人不清楚区别,导致消息丢失或重复。

快速科普

  • QoS 0:最多一次,发送后不管,适合不重要的遥测数据(如定时上报的库存信息)
  • QoS 1:至少一次,发送后等待 ACK,未收到则重发,适合大多数业务指令(如出货命令)
  • QoS 2:Exactly Once,消息一定会到达且不重复,但开销最大,适合交易关键节点

实战建议:出货指令用 QoS 1 加上消息去重(消息体内带唯一序列号),这套组合在自动售货机数据采集场景中最为常用,兼顾可靠性和性能。


问题四:4G 模块固件问题——容易被忽略的坑

使用 4G 模块(如 SIM7600)通讯的设备,掉线问题有时候不是 MQTT 配置的问题,而是模块本身断网了。

排查思路

  • 检查模块信号强度(AT+CSQ),低于 10 的环境下通讯极不稳定
  • 定期发送 AT 命令检测模块状态,一旦响应超时就复位模块
  • 在设备侧实现"网络层心跳"——每 5 分钟尝试一次 TCP 连接探测,不通就重启 4G 模块

这个方法在偏远地区无人售卖机通讯协议实践中验证过,有效降低了夜间断线投诉。


问题五:Topic 命名不规范——维护成本爆炸

设备多了之后,Topic 混乱是另一个常见问题。常见的反面案例:

  • 用设备 MAC 地址做 Topic,替换设备时所有订阅都要改
  • Topic 层级过深,超过 5 层,不好匹配

推荐命名规范

code复制

vending/{province}/{device_id}/telemetry
vending/{province}/{device_id}/command
vending/{province}/{device_id}/status

用设备 ID 做叶子节点而非整个 Topic,上层按区域或型号分类,便于批量订阅和管理。


三、总结

MQTT 通讯问题排查的核心就是三个字:连得上、活得稳、收得到

  • 连得上:心跳间隔对、重连退避策略正确
  • 活得稳:4G 模块固件健壮,定期自检
  • 收得到:QoS 等级匹配业务重要性,消息去重防重复

做好这五点,物联网无人售货机的通讯稳定性基本可以稳定在 99.5% 以上。当然,具体项目中还要结合 TLS 加密(安全传输层)和 OTA 升级(远程更新固件)等高级特性,这些内容值得单独开篇来讲~

更多推荐