einval断开重连的问题

版本: 5.8.0 (Open Source)
操作系统: debian 6.1.0

如图,设备在断开连接之前数据看着都是好的,但是不知道为什么突然断开了连接,并接着重连,我想知道原因,但是只显示了einval,这个是什么意思,是什么原因导致的连接断开,详情请查看附件
ww_3355111100000001.zip (66.3 KB)

einval 是socket 不可用:

大概率是

对已关闭的套接字进行操作:

  • 最常见的原因之一是尝试对一个已经关闭或正在关闭的套接字(Socket)执行操作(如发送、接收或设置选项)。
  • 这可能存在竞态条件(race condition),例如,一个进程关闭了套接字,而另一个进程几乎同时尝试使用该套接字。
  • 期望的错误可能是 {error, closed},但在某些情况下,底层的 inet 驱动或操作系统层面可能返回 einval。特别是在套接字刚刚关闭,其资源尚未完全释放时。

最有可能的是远端(可能是设备,也可能是网络不稳把 2 边都断开了)关闭了socket,emqx 还没有感知到,还在尝试给这条socket发信息,就会出现这个错。

有没有可能是速率的原因,我看上边还有一条警告是速率的限制

我觉得不太可能,如果可以很好重现的话,可以用 tcpdump 在 两端都抓包看看

不太好重现,因为我们观察到的现象是,每次掉线频率都固定在两小时左右,有时是两小时30分钟,有时是两小时10分钟

也就是说这个问题,不是emqx这边主动断开的连接,如果emqx这边主动断开,肯定是会有日志记录的,大概率设备端的问题是吧

我们目前也有这个问题,请问后来发现是什么原因了吗

这个现象通常不是 EMQX 主动踢连接,而是对端或中间网络先把 TCP 断了,EMQX 后续写 socket 才看到 einval
你提到掉线周期接近 2 小时,这个时间点很像网络设备或系统默认 TCP keepalive 周期(7200s)触发。
先做两步确认:

  1. 两端同时抓包,看谁先发 FIN/RST:
tcpdump -i any -nn host <client_ip> and port 1883 -w /tmp/mqtt.pcap
  1. 把掉线前后同一 clientid 的日志贴出来(至少前后 10 秒)。
    先做一个规避配置,降低空闲链路被中间设备回收概率:
listeners.tcp.default.tcp_options.keepalive = "240,30,5"
mqtt.keepalive_multiplier = 1.5

客户端 keepalive 也别设太大,建议先用 30~60s。
贴一下你这边的 EMQX 版本、客户端库和网络拓扑(是否经过 LB/NAT)。

我找到原因了,因为服务端的最大消息发布速率是60/60s,客户端固定单次单s发送了6.7条消息,导致限速了,message_burst=1 被冲了。所以云端有pause的日志,是不是emqx服务端直接暂停读写socket, 数据积压,最终对端或中间网络设备超时,发了个 RST 包把连接给断了,认为这个socket失效了?后来暂停1s之后写,发现socket不存在了,就报错了。就是很难理解为什么时间间隔是每次都固定的,有的客户端2h,有的6h,是数据积压到一定程度的原因?

版本是5.3.2