问题描述:
使用 org.eclipse.paho.client.mqttv3 连接emqx , 运行一段时间后出现掉线,而且不会自动重连(已设置自动重连,亲测有效),查看日志发现报以下错误:
[Timer-1] ERROR o.e.p.c.mqttv3.internal.ClientState - 445:
Timed out as no activity, keepAlive=120,000 lastOutboundActivity=1,571,456,370,788
lastInboundActivity=1,571,456,250,714 time=1,571,456,490,797 lastPing=1,571,456,370,788
自己写定时器去重连报以下错误:
org.eclipse.paho.client.mqttv3.MqttException: 客户机正在断开连接
at org.eclipse.paho.client.mqttv3.MqttAsyncClient.reconnect(MqttAsyncClient.java:1150)
at org.eclipse.paho.client.mqttv3.MqttClient.reconnect(MqttClient.java:624)
at com.legrand.middle.ware.iothub.mqttclient.MqttClientManage.siteServerReconnect(MqttClientManage.java:139)
at com.legrand.scheduled.MqttReconnectThread.run(MqttReconnectThread.java:75)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
问题分析:
抓包结果如下:其中229为Java程序,228为emqx服务,可以看出给Java程序给emqx服务发送TCP ZeroWindow ,告诉emqx服务自己的接收buffer已满,不要再发送数据了。同理心跳包也不能发送了 ,emqx服务收不到心跳包,认为客户端已不存活,故主动断开了连接。
那么问题来了:到底为什么tcp的接收buffer会满??
显然是因为emqx服务发送数据快,程序处理数据慢。审查代码才发现业务数据已经多线程处理,但emqx客户端的上下线消息并没有多线程处理,处理速度慢,导致tcp连接接收buffer被占满。
问题解决:
1、多线程处理 2、消息缓存起来 等等
总之原则是:尽量加快程序的处理速度
后话:遇到问题先考虑自己代码问题。曾经一度怀疑是网络、服务器、emqx框架不稳定。。。打脸了,惭愧惭愧。。。