MQTT服务器使用HTTP认证的实例代码
- rabbitmq_mqtt插件,提供MQTT协议的支持;
- rabbitmq_web_mqtt插件,提供Web MQTT协议的支持;
- rabbitmq_auth_backend_http插件,提供HTTP认证的支持。
- emqx_auth_http插件,用于认证和权鉴
- emqx_web_hook插件,用于客户端连接和断开等动作的时候感知到其行为。
消息丢失有两个方面的原因,一是QoS等级配置,二是会话id配置。
首先对于QoS等级来说,因为存在推送端发往服务器和服务器发往接收端两个过程,所以消息的最终QoS是取决于两者中较低的一个。比如我们项目中一开始服务器端QoS是1,但是Android端订阅的QoS等级是0,就导致了手机端经常收不到消息,而mqtt服务器显示消息已发送。这个问题在Android端更改QoS等级为1后得到了解决。
其次,如果客户端断开了和MQTT服务器的连接,当Qos等级为0时,离线消息将被丢弃,当QoS等级为1时,离线消息插入队列。但是在使用过程中发现,客户端重连后旧队列连同消息被销毁,重新创建了一个新的队列。查阅文档后发现,要正确接收到离线消息,必须设置QoS等级1以上,会话id保持不变。对于paho来说,建立连接时必须指定cleanSession参数为false。
这个问题表现和上个问题一样,但只在外网发生,即无法收到MQTT消息,导致一直没有成功定位,耗费了大量的时间。
考虑到耗电问题,Android客户端的MQTT心跳时间设置为20分钟。而在国内网络环境下,网络运营商大量使用NAT技术,而NAT设备会淘汰不活跃的连接。TCP是一个无状态的协议,客户端未接收到RST包,因此在发送心跳包前都无法得知连接状态。NAT设备的淘汰算法无法得知,经测试淘汰时间也不固定,因此只能通过缩减心跳时间来解决。
经测试,心跳时间设置为3分钟能很好收到消息,最久的一次在20s后收到;心跳时间设置为5分钟时,连接断开较为频繁,经常在1分钟后才接收到推送消息。
在客户端connect连接的时,会有一个clientId 参数,需要每个客户端都保持唯一的。