求助在设备离线消息获取问题?

使用的EMQX 版本为 [5.8.4 (Open Source)]

$SYS/brokers/${node}/clients/connected 和disconnected 事件中,怎么没有连接属性,用的MQTT V5 协议连接也没有? 这正常么?

$events/client_connected 和 disconnected 事件中有连接属性,但在离线事件中不带对应的上线时间? 而系统主题中的离线事件,却带 对应的上线时间 这正常么?

$events/client_disconnected 事件中,可以带上对应的上线时间么? 因为在实际测试中,客户端网络不好的情况下,设备会多次断开重连,其中断开消息会晚于最新的在线消息,导致覆盖掉最新的消息;

实测数据如下:
序号为1的离线事件,是序号3 在线事件对应的事件
序号2 为设备的最终状态,但序号3 的离线事件,在业务逻辑中不特殊处理的情况下,会覆盖掉设备的最终状态

 1、 {\"ipaddress\":\"36.110.46.106\",\"disconnected_at\":1740160870627,\"sockport\":8883,\"connected_at\":1740160813688,\"proto_name\":\"MQTT\",\"proto_ver\":5,\"clientid\":\"80482C7B0FE8\",\"username\":\"80482C7B0FE8\",\"ts\":1740160870627,\"protocol\":\"mqtt\",\"reason\":\"ssl_closed\"}"
 2、 {\"ipaddress\":\"36.110.46.106\",\"expiry_interval\":5000,\"clean_start\":false,\"sockport\":8883,\"connected_at\":1740160856111,\"proto_name\":\"MQTT\",\"proto_ver\":5,\"clientid\":\"80482C7B0FE8\",\"username\":\"80482C7B0FE8\",\"ts\":1740160856111,\"protocol\":\"mqtt\",\"keepalive\":60}"
 3、 {\"ipaddress\":\"36.110.46.106\",\"expiry_interval\":5000,\"clean_start\":false,\"sockport\":8883,\"connected_at\":1740160813688,\"proto_name\":\"MQTT\",\"proto_ver\":5,\"clientid\":\"80482C7B0FE8\",\"username\":\"80482C7B0FE8\",\"ts\":1740160813688,\"protocol\":\"mqtt\",\"keepalive\":60}"
 4、 {\"ipaddress\":\"36.110.46.106\",\"disconnected_at\":1740160807434,\"sockport\":8883,\"connected_at\":1740139101779,\"proto_name\":\"MQTT\",\"proto_ver\":5,\"clientid\":\"80482C7B0FE8\",\"username\":\"80482C7B0FE8\",\"ts\":1740160807434,\"protocol\":\"mqtt\",\"reason\":\"ssl_closed\"}"

在系统主题中每个离线事件有在线时间,可以根据在线时间判断,是否要丢弃到该离线事件;但通过规则引擎过来的数据离线数据,不带上线时间,就无法做这个判断;

正常,不过可以当一个 feature加到下个版本里。

也正常,后续可以在 disconnect 里面加上 connected_at时间。
这样,处理流程

  1. 收到 disconnect 事件时,存上connected_at时间。
  2. 收到下一个 disconnect 事件,对比 connected_at 时间,如果大于 1 中的时间就更新,否则就直接忽略。

我觉得这是一个非常好的需求建议!看看你还有什么要补充的么

1 个赞

没有要补充的了,期待这两个更新 :pray:

1 个赞

在大量设备同时反复断线后重连的情况下还是会出现这个问题,disconnect_at和connected_at这2个时间戳会是一样的。

我是用的http的webhook,这种情况是不是需要在webhook里面配置请求为同步才行?

[connectHook,63] - Connection, clientid: IN1008146, connected at: 1751450998554, disconnect at: null
[connectHook,63] - Connection, clientid: IN1008146, connected at: null, disconnect at: 1751450998554
如上面这种情况,在大量设备反复离线上线的情况下,同一个clientid的connect_at和disconnect_at都是1751450998554,导致无法区分最终到底是在线还是离线状态了。

你可以看看这个兄弟是怎么解决的,我觉得他写得蛮清晰的

这个兄弟的问题是离线和上线时间不相等的情况下,可以通过时间来确定最终状态。我遇到的问题是上线和离线时间相等,无法根据时间来区分,当然也有解决办法,就是对于这种时间相等的情况调用API进行查询获取最终状态进行纠正。

这个毫秒级的相等应该是极小概率事件,
你提供的日志,我猜测是之前的版本,更新后可以在disconnect事件中看到connected at的时间,这个才是对的,而不是只用用相同的clientid去看。因为可能存在相同client互相挤下线的情况

对,就是极端情况下的概率事件。
这个问题的复现情况如下:
1.用nginx代理转发到emqx,
2.用客户端工具创建1w个连接
3.1w连接还未完全连接完的情况下重启nginx
4.间隔不定时反复第3步操作几次,比如连接到8000个的时候就进行重启,其中就有10-20个连接会出现这种情况。
我用的5.8.4版本,我看5.8.6版本的disconnect加了这个connected_at,但是这个connected_at和disconnected_at的逻辑没变化,这种毫秒一致的极端情况应该还是存在,目前就是对这种情况调用API获取最终状态纠正。

我觉得不存在,你更新试试。