自定义插件, 回应的连接和断开连接时间顺序不对?

环境

  • EMQX 版本:5.4.1
  • 操作系统版本:ubuntu22.4

重现此问题的步骤

  1. 嵌入式团队开发的网关通过mqtt连接上EMQX
  2. 将网关断电重启
  3. EMQX自定义插件给我们回应的连接和断开时间顺序不对
    4.先回应连接事件、再回应断开连接,结果网关还连接在Broker上

连接报文:
emqx_plugin_hook:on_client_connected/3(110), peername: 192.168.20.1:42800, clientid: a1gmxxxxxxT.xxxxxxxx|, clientinfo: #{clientid => <<“a1gmxxxxxxT.xxxxxxxx|”>>,cn => undefined,dn => undefined,enable_authn => true,is_bridge => false,is_superuser => false,listener => ‘tcp:default’,mountpoint => undefined,peerhost => {192,168,20,1},peerport => 42800,protocol => mqtt,sockport => 1883,username => <<“1FlOxxxxxxx6T”>>,zone => default}, connInfo: #{clean_start => true,clientid => <<“a1gmxxxxxxT.xxxxxxxx|”>>,conn_mod => emqx_connection,conn_props => #{},connected_at => 1732514733921,expiry_interval => 0,keepalive => 150,peercert => ,peername => {{192,168,20,1},42800},proto_name => <<“MQTT”>>,proto_ver => 4,receive_maximum => 32,sockname => {{192,168,20,135},1883},socktype => proxy,username => <<“1FlOxxxxxxx6T”>>}

断开连接报文:
emqx_plugin_hook:on_client_disconnected/4(132), peername: 192.168.20.1:46714, clientid: a1gmxxxxxxT.xxxxxxxx|, clientinfo: #{clientid => <<“a1gmxxxxxxT.xxxxxxxx|,”>>,cn => undefined,dn => undefined,enable_authn => true,is_bridge => false,is_superuser => false,listener => ‘tcp:default’,mountpoint => undefined,peerhost => {192,168,20,1},peerport => 46714,protocol => mqtt,sockport => 1883,username => <<“1FlOxxxxxxx6T”>>,zone => default}, conninfo: #{clean_start => true,clientid => <<“a1gmxxxxxxT.xxxxxxxx|,”>>,conn_mod => emqx_connection,conn_props => #{},connected_at => 1732514497884,disconnected_at => 1732514733998,expiry_interval => 0,keepalive => 150,peername => {{192,168,20,1},46714},proto_name => <<“MQTT”>>,proto_ver => 4,receive_maximum => 32,sockname => {{192,168,20,135},1883},socktype => proxy,username => <<“1FlOxxxxxxx6T”>>}, reason: tcp_closed

预期行为

1、连接与断开连接顺序问题,应该是断开连接在前,连接在后
2、reason原因问题,我们抓取嵌入式那边tcp连接报文,没看到FIN数据包

实际行为

连接在前,断开连接在后, 这就导致我们很难判断该设备最新的状态

这个 connected 比 disconnected 早了 77 ms,原因也应该是断电后 emqx 根本没有在 tcp 层感应到断开。如果想让emqx 更快速的感应到断开,可以设置通过这个配置来控制 tcp 层的 keepalive Configuration Manual | EMQX 5.8.2 Docs

  1. TCP Keepalive 参数
  • tcp_keepalive_time:空闲连接发送探测报文的时间间隔
  • tcp_keepalive_intvl:探测报文的发送间隔
  • tcp_keepalive_probes:发送探测报文的最大次数

但是要想做到理想中的断电马上就 disconnect 是非常难的(目前做不到)

第一:我们不是立马想知道设备离线。只是设备在MQTT的keepalive时间内,启动了设备,理论上是先踢掉之前的设备连接,在允许现在的连接,因为它们的clientid是一样。但是我们现在得到为啥是个并发现象,有时候像上面的结果,有时候他的结果顺序是对的。

第二: 我看你们文档,tcp_closed是因为端发送了TCP的FIN数据包导致,我们昨天下午抓了一下午的包,也没看到TCP的FIN数据包

第三: 有一点我很好奇,我用java语言去模拟设备过程,它又是正常的,java语言实现的结果是,EMQX会先踢掉之前的客户端,状态为discarded,然后在允许连接,这个现象才是正常的。这里就很奇怪,为啥到设备上顺序不对了,并且状态也变成了tcp_closed

目前,我们也没有什么好的解决方案?就想请问你们这边有没有遇见过类似的问题,怎么解决的

上面那个就是根据客户反馈的设备断电后无法及时感知,才增加的参数。
没有其他解决方案。