# MQTT 协议简介
MQTT 是一个轻量的发布订阅模式消息传输协议,专门针对低带宽和不稳定网络环境的物联网应用设计。
MQTT 官网: http://mqtt.org (opens new window)
MQTT v3.1.1 协议规范: http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html (opens new window)
MQTT v5.0 协议规范: https://docs.oasis-open.org/mqtt/mqtt/v5.0/mqtt-v5.0.html (opens new window)
# 特点
- 开放消息协议,简单易实现
- 发布订阅模式,一对多消息发布
- 基于 TCP/IP 网络连接
- 1字节固定报头,2字节心跳报文,报文结构紧凑
- 消息 QoS 支持,可靠传输保证
# 应用
MQTT 协议广泛应用于物联网、移动互联网、智能硬件、车联网、电力能源等领域。
- 物联网 M2M 通信,物联网大数据采集
- Android 消息推送, WEB 消息推送
- 移动即时消息,例如 Facebook Messenger
- 智能硬件、智能家具、智能电器
- 车联网通信,电动车站桩采集
- 智慧城市、远程医疗、远程教育
- 电力、石油与能源等行业市场
# MQTT 基于主题 (Topic) 消息路由
MQTT 协议基于主题 (Topic) 进行消息路由,主题 (Topic) 类似 URL 路径,例如:
chat/room/1 sensor/10/temperature sensor/+/temperature $SYS/broker/metrics/packets/received $SYS/broker/metrics/#
Copied!
2
3
4
5
6
7
8
9
主题 (Topic) 通过/
分割层级,支持+
, #
通配符:
'+': 表示通配一个层级,例如a/+,匹配a/x, a/y '#': 表示通配多个层级,例如a/#,匹配a/x, a/b/c/d
Copied!
2
3
订阅者与发布者之间通过主题路由消息进行通信,例如采用mosquitto命令行发布订阅消息:
mosquitto_sub -t a/b/+ -q 1 mosquitto_pub -t a/b/c -m hello -q 1
Copied!
2
3
订阅者可以订阅含通配符主题,但发布者不允许向含通配符主题发布消息。
# MQTT V3.1.1协议报文
# 报文结构
- 固定报头 (Fixed header)
- 可变报头 (Variable header)
- 报文有效载荷 (Payload)
# 固定报头
+----------+-----+-----+-----+-----+-----+-----+-----+-----+ | Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | +----------+-----+-----+-----+-----+-----+-----+-----+-----+ | byte1 | MQTT Packet type | Flags | +----------+-----------------------+-----------------------+ | byte2... | Remaining Length | +----------+-----------------------------------------------+
Copied!
2
3
4
5
6
7
# 报文类型
类型名称 | 类型值 | 报文说明 |
---|---|---|
CONNECT | 1 | 发起连接 |
CONNACK | 2 | 连接回执 |
PUBLISH | 3 | 发布消息 |
PUBACK | 4 | 发布回执 |
PUBREC | 5 | QoS2消息回执 |
PUBREL | 6 | QoS2消息释放 |
PUBCOMP | 7 | QoS2消息完成 |
SUBSCRIBE | 8 | 订阅主题 |
SUBACK | 9 | 订阅回执 |
UNSUBSCRIBE | 10 | 取消订阅 |
UNSUBACK | 11 | 取消订阅回执 |
PINGREQ | 12 | PING请求 |
PINGRESP | 13 | PING响应 |
DISCONNECT | 14 | 断开连接 |
# PUBLISH 发布消息
PUBLISH 报文承载客户端与服务器间双向的发布消息。 PUBACK 报文用于接收端确认 QoS1 报文,PUBREC/PUBREL/PUBCOMP 报文用于 QoS2 消息流程。
# PINGREQ/PINGRESP 心跳
客户端在无报文发送时,按保活周期 (KeepAlive) 定时向服务端发送 PINGREQ 心跳报文,服务端响应 PINGRESP报文。PINGREQ/PINGRESP 报文均2个字节。
# MQTT 消息 QoS
MQTT 发布消息 QoS 保证不是端到端的,是客户端与服务器之间的。订阅者收到 MQTT 消息的 QoS 级别,最终取决于发布消息的 QoS 和主题订阅的 QoS。
发布消息的 QoS | 主题订阅的 QoS | 接收消息的 QoS |
---|---|---|
0 | 0 | 0 |
0 | 1 | 0 |
0 | 2 | 0 |
1 | 0 | 0 |
1 | 1 | 1 |
1 | 2 | 1 |
2 | 0 | 0 |
2 | 1 | 1 |
2 | 2 | 2 |
# Qos0 消息发布订阅
# Qos1 消息发布订阅
# Qos2消息发布订阅
# MQTT 会话 (Clean Session)
MQTT 客户端向服务器发起 CONNECT 请求时,可以通过 Clean Session
标志设置会话。
Clean Session
设置为0,表示创建一个持久会话,在客户端断开连接时,会话仍然保持并保存离线消息,直到会话超时注销。
Clean Session
设置为1,表示创建一个新的临时会话,在客户端断开时,会话自动销毁。
# MQTT 连接保活心跳
MQTT 客户端向服务器发起 CONNECT 请求时,通过 KeepAlive 参数设置保活周期。
客户端在无报文发送时,按KeepAlive周期定时发送2字节的 PINGREQ 心跳报文,服务端收到 PINGREQ 报文后,回复2字节的 PINGRESP 报文。
服务端在1.5个心跳周期内,既没有收到客户端发布订阅报文,也没有收到 PINGREQ 心跳报文时,主动心跳超时断开客户端 TCP 连接。
EMQX 消息服务器默认按最长 2.5 心跳周期超时设计。
# MQTT 遗嘱消息 (Last Will)
MQTT 客户端向服务器端 CONNECT 请求时,可以设置是否发送遗嘱消息 (Will Message) 标志,和遗嘱消息主题(Topic) 与内容 (Payload)。
MQTT 客户端异常下线时(客户端断开前未向服务器发送 DISCONNECT 消息),MQTT 消息服务器会发布遗嘱消息。
# MQTT 保留消息 (Retained Message)
MQTT 客户端向服务器发布 (PUBLISH) 消息时,可以设置保留消息 (Retained Message) 标志。保留消 (Retained Message) 会驻留在消息服务器,后来的订阅者订阅主题时仍可以接收该消息。
例如 mosquitto 命令行发布一条保留消息到主题 a/b/c
:
mosquitto_pub -r -q 1 -t a/b/c -m 'hello'
Copied!
之后连接上来的 MQTT 客户端订阅主题 a/b/c
时候,仍可收到该消息:
$ mosquitto_sub -t a/b/c -q 1 hello
Copied!
2
保留消息 (Retained Message) 有两种清除方式:
- 客户端向有保留消息的主题发布一个空消息:
mosquitto_pub -r -q 1 -t a/b/c -m ''
Copied!
- 消息服务器设置保留消息的超期时间。
# MQTT WebSocket 连接
MQTT 协议除支持 TCP 传输层外,还支持 WebSocket 作为传输层。通过 WebSocket 浏览器可以直连 MQTT 消息服务器,发布订阅模式与其他 MQTT 客户端通信。
MQTT 协议的 WebSocket 连接,必须采用 binary 模式,并携带子协议 Header:
Sec-WebSocket-Protocol: mqttv3.1 或 mqttv3.1.1
Copied!
# MQTT 与 XMPP 协议对比
MQTT 协议设计简单轻量、路由灵活,将在移动互联网物联网消息领域,全面取代 PC 时代的 XMPP 协议:
- MQTT 协议一个字节固定报头,两个字节心跳报文,报文体积小编解码容易。XMPP 协议基于繁重的 XML,报文体积大且交互繁琐。
- MQTT 协议基于主题 (Topic) 发布订阅模式消息路由,相比 XMPP 基于 JID 的点对点消息路由更为灵活。
- MQTT 协议未定义报文内容格式,可以承载 JSON、二进制等不同类型报文。XMPP 协议采用 XML 承载报文,二进制必须 Base64 编码等处理。
- MQTT 协议支持消息收发确认和 QoS 保证,XMPP 主协议并未定义类似机制。MQTT 协议有更好的消息可靠性保证。