环境: 语言 Java emq版本:emqx-windows7-v3.1.1
emq客户端配置:
问题描述:
emq平常能正常运行,发送和接收数据都没有问题,在与设备调试过程中突然出现掉线重连,重启程序服务也无法解决,需要重启emq服务才行。
问题分析:可能原因
1、重复clientId 排除,确定没有重复clientId
2、网络问题导致没有收到心跳 排除,因为程序和emq服务器在同一台电脑上不存在网络问题,而且重连的请求emq也能收到。
3、代码报错,导致emq服务连不上 极大可能
因为之前是可以的,后面才出现问题,经和设备开发人员沟通,发现是设备回复了错误的保留信息,程序解析出错,而且没有捕捉该错误,至此问题定位成功。这也能解释为什么重启emq服务器后就暂时不会出现该问题,因为emq不提供持久化功能,数据都存在内存里,重启emq服务后,保存内存的数据也被清空。
保留消息定义
如果PUBLISH消息的RETAIN标记位被设置为1,则称该消息为“保留消息”;
Broker对保留消息的处理
Broker会存储每个Topic的最后一条保留消息及其Qos,当订阅该Topic的客户端上线后,Broker需要将该消息投递给它。
问题重现:
可以使用emq客户端,往主题发送保留的错误消息:
错误消息:随便造,解析不了报错就可以
解决方案:
1、 根据对保留消息的理解,那么我们就可以在收到错误的保留消息处理出错时,捕捉该错误,并往该主题发送保留的空白消息以替换之前的错误消息。
代码如下:
@Override
public void messageArrived(String topic, MqttMessage message)
throws Exception {
String data = new String(message.getPayload(),"UTF-8");
Map<String, Object> revDataMap=new HashMap<>(16);
try {
revDataMap = JSONConext.getResultMap(data);
}catch (Exception e){
/**
* emq不断重连问题修复
* 原因:收到保留的错误消息
* 解决方案:往该主题发送空的保留消息 替换掉之前的错误消息
* retained 为true时 保留
*
*/
byte[] bytes = new byte[0];
LoginClientManage.getSiteServerClient().getMqttClient().publish(topic, bytes, ParCfg.getInstance().getDefalutQoS(), true);
logger.error("错误保留消息:"+message.toString());
logger.error("接收到错误保留消息,执行清空该保留消息:"+e);
return;
}
}
2、cleanSession 设置为true ,会话不保留 ,保留的消息也不复存在。不过会话清除,重连后需要重新订阅主题,重连之前的消息也收不到了。看业务需要使用吧。
参考文档:
1、https://blog.csdn.net/yangguosb/article/details/78668756
2、https://blog.csdn.net/u011267225/article/details/81982515