关于EMQX订阅端无消息问题

场景

由于MQTT客户端数量较多,订阅端最近每隔5、6个小时就会空转,无消息进来。从 Dashboard 界面来看,显示连接正常。但是无消息进来。

问题解决

查看 Dashboard 的报警消息有如下:

connection congested: #{buffer => 4096,clientid => ...

同时,找到连接管理的客户端ID,点击链接查看:发现飞行窗口、消息队列已满。

通过社区搜索相关问题发现是订阅端消息太多处理不及时导致!根本原因就是:客户端消费能力不足。相关问题:订阅者的消息队列满 – EMQX – EMQ 问答社区

由于 emqx 5.0 版本以上已经支持 MQTT 3.1.1 协议的 共享订阅,所以直接将主题订阅转为共享订阅,然后开启多进程处理即可~

详见:共享订阅 | EMQX 5.0 文档

刨根问底

为何程序会处于正常状态也没有异常?

更正:

经过几个小时的深度调研,找到以下原因:

1、我的订阅使用的 QoS 为 1
根据官方文档描述,当 QoS 为 1 时:emq 会将订阅端无法及时 ack 的消息先放入 飞行窗口,如果飞行窗口已满则放入消息队列(注:QoS 0 不受此影响会立即转发)。飞行窗口和消息队列 | EMQX 5.0 文档

2、订阅端 QoS 1 的确认时间,缺省超时为

3、如果订阅端消费能力不足,则在规定时间内无法发送 ack,导致飞行窗口无法空出继续停止发送。

4、后续订阅端消费完但是 ack 已超时,则导致一直空载等待消息到来

— 以下为原猜测 —

原因应该是订阅方的 TCP 消息接受缓冲区被填满导致,之后触发了零窗口问题,进而导致发送方 broker 不再发送后续积压数据。订阅方虽然连接正常 keeplive,但无数据进来导致程序在消耗完缓冲区数据后一直空载运行。

但是为何订阅方消费完缓冲区后,双方数据没有恢复的问题,暂时还未找到答案,也许是正好丢包了?等回头有时间了,再详细探究一下

示例图

EMQX 避坑 – 订阅和共享订阅本文讨论了 EMQX 中使用订阅和共享订阅模式处理服务端业务的局限性,并且提出了对应的 – 掘金

Author: thinkwei

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注