生产环境MQTT频繁丢消息问题排查咨询
MQTT生产环境消息丢失问题排查咨询
生产环境部署架构
- 5台EMQX Broker(版本3.X)
- 负载均衡:AWS负载均衡器(部分环境使用HAProxy)实现Broker负载分发
- 客户端:Paho MQTT Python客户端(版本1.1)
问题现象
生产环境中存在消息频繁丢失问题,约每100条消息丢失1-2条:
- 丢失的消息,Paho MQTT的
publish方法返回0(表示发布成功) - 即使开启EMQX DEBUG日志,也无这些丢失消息的记录
- 仅在多Celery Worker并行向同一主题发布时出现,单客户端场景无此问题
MQTT连接配置
client_id = "<random_int_from_1_to_100>_<current_hostname>" clean_session = False keep alive timeout = 60
消息发布细节
- X个Celery Worker并行发布,消息速率最高10条/秒
- 每个Worker的
client_id唯一(包含主机名) - 发布代码示例:
(res, mid) = self.conn.publish(topic=topic, payload=payload, qos=qos) if res == 0: log.debug(f"Succesfully published message::{str(res)} with id {mid} for payload::{payload}", client_id=self.client_id) else: log.info(f"Error publishing message::{str(res)} with id {mid} for payload::{payload}", client_id=self.client_id)
补充环境信息
- Python版本:3.6.9
- Paho MQTT版本:1.1
- 操作系统:Linux
- MQTT服务器:EMQX 3.X,搭配对应负载均衡部署
问题解答
一、当前配置的潜在问题
clean_session=False的误用风险
发布端开启clean_session=False会让Broker持久化该客户端的会话状态,大量并行客户端会增加Broker会话存储压力,极端情况下可能引发会话清理异常,间接导致消息丢失。发布端无需持久化会话,建议设置clean_session=True,减少Broker不必要的资源消耗。负载均衡的MQTT适配问题
AWS负载均衡或HAProxy若未正确配置MQTT协议支持:- 未开启TCP长连接保持,会导致连接被负载均衡主动断开,此时客户端误以为消息已发送,但实际未到达Broker
- 未配置会话粘滞(Sticky Session),当
clean_session=False时,同一客户端的后续请求被分发到不同Broker,会导致会话状态不一致,引发消息丢失
QoS配置未明确的隐患
- 若使用QoS 0,客户端
publish返回0仅表示消息写入本地TCP缓冲区,不代表Broker已接收,网络波动或Broker过载时消息易丢失 - 若使用QoS 1/2,Paho 1.1版本存在异步确认逻辑Bug,会导致客户端误判消息已发布成功
- 若使用QoS 0,客户端
二、升级Paho MQTT库的作用
Paho MQTT Python 1.1版本存在多个已知缺陷:
- 异步发布时的QoS确认逻辑错误,客户端提前返回成功状态,但实际消息未被Broker确认
- 长连接场景下心跳处理异常,可能导致连接静默断开而客户端未感知
- 并发发布时的线程安全问题,多Worker共享连接(若存在此情况)会引发消息丢失
升级到最新稳定版(如2.0+)可修复上述大部分Bug,尤其是QoS确认逻辑和线程安全问题,大概率能缓解甚至解决消息丢失问题,且新版本对Python 3.6+兼容性良好,无需大幅修改代码。
三、是否为EMQX 3.X特有问题
EMQX 3.X存在集群消息转发缺陷:
- 多Broker集群中,客户端发布消息到某台Broker后,集群内消息同步延迟或失败,导致订阅端无法收到消息,但Broker日志可能无记录
- 高并发场景下,Broker消息队列溢出会直接丢弃未持久化的消息
但你的问题中Broker无丢失消息的日志,更可能是客户端-负载均衡环节的问题,而非EMQX特有。不过升级EMQX到4.X或5.X版本,可获得更稳定的集群同步机制和更完善的日志监控,有助于排查此类问题。
内容的提问来源于stack exchange,提问作者Kashyap KN
相关产品推荐
相关产品推荐

