1-MQTT基础知识
MQTT 是一个轻型协议,使用基于 TCP/IP 协议的发布/订阅消息转发模式,专门用于机器对机器 (M2M) 通信。
由于物联网的环境是非常特别的,所以MQTT遵循以下设计原则:
- 精简,不添加可有可无的功能。
- 发布/订阅(Pub/Sub)模式,方便消息在传感器之间传递。
- 允许用户动态创建主题,零运维成本。
- 把传输量降到最低以提高传输效率。
- 把低带宽、高延迟、不稳定的网络等因素考虑在内。
- 支持连续的会话控制。
- 理解客户端计算能力可能很低。
- 提供服务质量管理。
- 假设数据不可知,不强求传输数据的类型与格式,保持灵活性。
1. MQTT整体流程
MQTT 协议的中心是 MQTT 服务器或代理 (broker) ,支持发布程序和订阅程序进行访问,如下图所示
graph LR
发布者-->Broker
Broker-->订阅者
订阅者-->Broker
- 订阅者在连接上Broker之后,订阅想要收到消息的主题(local/test)
- 发布者通过主题(local/test),发送想要发送的内容(payload)
- Broker收到发布者发送的内容,根据主题转发到已经订阅了该主题的订阅者
- 订阅者收到主题(local/test)的内容,解析需要的数据
2. MQTT消息类型
MQTT拥有14种不同的消息类型:
CONNECT:客户端连接到MQTT代理
CONNACK:连接确认
PUBLISH:新发布消息
PUBACK:新发布消息确认,是QoS 1给PUBLISH消息的回复
PUBREC:QoS 2消息流的第一部分,表示消息发布已记录
PUBREL:QoS 2消息流的第二部分,表示消息发布已释放
PUBCOMP:QoS 2消息流的第三部分,表示消息发布完成
SUBSCRIBE:客户端订阅某个主题
SUBACK:对于SUBSCRIBE消息的确认
UNSUBSCRIBE:客户端终止订阅的消息
UNSUBACK:对于UNSUBSCRIBE消息的确认
PINGREQ:心跳
PINGRESP:确认心跳
DISCONNECT:客户端终止连接前优雅地通知MQTT代理
后面我们会给出具体的例子。
3. 主题
MQTT是通过主题对消息进行分类的,本质上就是一个UTF-8的字符串,不过可以通过反斜杠表示多个层级关系。主题并不需要创建,直接使用就是了。
主题还可以通过通配符进行过滤。其中,+可以过滤一个层级,而#只能出现在主题最后表示过滤任意级别的层级。
举个例子:
building-b/floor-5:代表B楼5层的设备。
+/floor-5:代表任何一个楼的5层的设备。
building-b/#:代表B楼所有的设备。
注意,MQTT允许使用通配符订阅主题,但是并不允许使用通配符广播。
4. WILL主题
WILL主题也叫遗嘱消息,是一个特殊的主题。
客户端连接Broker的时候,附带一个will主题和will主题对应的内容。
当客户端与Broker断开连接时,Broker将该WILL主题的内容发送给相关的订阅者的遗嘱消息,这样订阅者就知道该客户端已经离线了。
以下情况下会发送 Will Message:
- 服务端发生了I/O 错误或者网络失败;
- 客户端在定义的心跳时期失联;
- 客户端在发送下线包之前关闭网络连接;
- 服务端在收到下线包之前关闭网络连接。
注:在客户端正常调用 disconnect 方法之后并不会被发送。
5. 服务质量QOS
为了满足不同的场景,MQTT支持三种不同级别的服务质量(Quality of Service,QoS)为不同场景提供消息可靠性:
- QOS=0,最多一次,就发一次,没有重传,会丢失
- QOS=1,至少一次,会重传,会出现收到多次消息
- QOS=2,只有一次,只会收到一次
级别2所提供的不重不丢很多情况下是最理想的,不过往返多次的确认一定对并发和延迟带来影响。
级别1提供的至少一次语义在日志处理这种场景下是完全OK的,所以像Kafka这类的系统利用这一特点减少确认从而大大提高了并发。
级别0适合鸡肋数据场景,基本就没怎么用了。
6. clean session
客户端在连接的时候可以设置clean session,如果设置成true说明在设备离线后broker不保存,设置成false说明在设备离线后broker保存消息,等上线的时候就发送给他。
7. 心跳
客户端在连接Broker的时候,会指定心跳的时候。连接成功之后,客户端就按照这个心跳时间定时发送心跳数据给Broker,如果Broker在1.5T时间内没有收到客户端的心跳数据,则判定改设备已经离线,发送WILL主题广播告诉别人该设备已离线。
8. SSL加密
MQTT可以使用SSL加密方式传输,设备的认证有单向认证和双向认证两种:
- 不管单向还是双向,broker端都需要配置cafile、certfile、keyfile
- 单向的时候,client只需要提供cafile,双向的时候client需要提供cafile、certfile、keyfile
- 双向的时候,broker需要将
require_certificate
和use_identity_as_username
设置成true
9. 连接账号密码
MQTT除了有SSL加密之外,对于连接也有账号密码的授权,只要账号密码正确的才可以连接成功。
MQTT 协议和mosquitto:https://shaocheng.li/posts/2015/08/11/
物联网网关协议比较MQTT 和 Modbus:
https://software.intel.com/pt-br/node/628992?language=es