MQTT协议初识


MQTT

mqtt的工作原理 :

发布者发布主题会传到服务器, 由服务器下发到订阅该主题的订阅者.并非发布者和订阅者直接对接.

MQTT协议特点

MQTT是一个基于客户端-服务器的消息发布/订阅传输协议。

MQTT协议是轻量、简单、开放和易于实现的,这些特点使它适用范围非常广泛。在很多情况下,包括受限的环境中,如:机器与机器(M2M)通信和物联网(IoT)。

发布和订阅

MQTT使用的发布/订阅消息模式,它提供了一对多的消息分发机制,从而实现与应用程序的解耦。

这是一种消息传递模式,消息不是直接从发送器发送到接收器(即点对点),而是由MQTT server(或称为 MQTT Broker)分发的。

发布与订阅原理
发布与订阅原理

MQTT 服务器是发布-订阅架构的核心

客户端可以发布消息(发送方)、订阅消息(接收方)或两者兼而有之。

客户端(也称为节点)是一种智能设备,如微控制器或具有 TCP/IP 堆栈和实现 MQTT 协议的软件的计算机。

消息在允许过滤的主题下发布。主题是分层划分的 UTF-8 字符串。不同的主题级别用斜杠/作为分隔符号。

我们来看看下面的设置。

光伏发电站是发布者(Publisher)。

主要主题(Topic)级别是”PV”,这个工厂发布两个子级别”sunshine”和”data”;

“PV/sunshine”是一个布尔值(true/false,也可以是 1/0),充电站需要它来知道是否应该装载电动汽车(仅在阳光普照时 :))。

充电站(EVSE)是订阅者,订阅”PV/sunshine”从服务器获取信息。

“PV/data” 另一方面,以 kW 为单位传输工厂产生的瞬时功率,并且该主题可以例如通过计算机或平板电脑订阅,以生成一天内传输功率的图表。

这就是一个简单的MQTT的应用场景,具体如下图所示:

光伏发电的MQTT应用
光伏发电的MQTT应用

QOS

服务质量是 MQTT 的一个重要特性。当我们使用 TCP/IP 时,连接已经在一定程度上受到保护。但是在无线网络中,中断和干扰很频繁,MQTT 在这里帮助避免信息丢失及其服务质量水平。这些级别在发布时使用。如果客户端发布到 MQTT 服务器,则客户端将是发送者,MQTT 服务器将是接收者。当MQTT服务器向客户端发布消息时,服务器是发送者,客户端是接收者。

QoS 0

这一级别会发生消息丢失或重复,消息发布依赖于底层TCP/IP网络。

至多一次(qos = 0),可能会出现丢包的现象。使用在对实时性要求不高的情况。这一级别可应用于如下情景,如环境传感器数据,丢失一次读记录无所谓,因为很快下一次读记录就会产生。

QoS 1

QoS 1 承诺消息将至少传送一次给订阅者。

至少一次(qos = 1),保证包会到达目的地,但是可能出现重包。

QoS 2

使用 QoS 2,我们保证消息仅传送到目的地一次。为此,带有唯一消息 ID 的消息会存储两次,首先来自发送者,然后是接收者。QoS 级别 2 在网络中具有最高的开销,因为在发送方和接收方之间需要两个流。

正好一次(qos = 2),保证包会到达目的地,且不会出现重包的现象。这一级别可用于如计费系统等场景,在计费系统中,消息丢失或重复可能会导致生成错误的费用。

MQTT数据包结构

  • 固定头(Fixed header),存在于所有MQTT数据包中,表示数据包类型及数据包的分组类标识;

  • 可变头(Variable header),存在于部分MQTT数据包中,数据包类型决定了可变头是否存在及其具体内容;

    • 较常的应用是做为包的标识
  • 消息体(Payload),存在于部分MQTT数据包中,表示客户端收到的具体内容;

    • CONNECT、SUBSCRIBE、SUBACK、UNSUBSCRIBE四种类型的消息 有消息体:
      • CONNECT,消息体内容主要是:客户端的ClientID、订阅的Topic、Message以及用户名和密码
      • SUBSCRIBE,消息体内容是一系列的要订阅的主题以及QoS
      • SUBACK,消息体内容是服务器对于SUBSCRIBE所申请的主题及QoS进行确认和回复。
      • UNSUBSCRIBE,消息体内容是要取消订阅的主题。

使用MQTT进行交互

当应用数据通过MQTT网络发送时,MQTT会把与之相关的服务质量(QoS)和主题名(Topic)相关连。

在MQTT客户端上干什么?

  • 发布其他客户端会订阅的信息
  • 订阅其它客户端发布的消息
  • 退订或删除应用程序的消息
  • 断开与服务器连接。

MQTT服务器又干什么?

  • 接受来自客户的网络连接
  • 向订阅的客户转发应用程序消息

MQTT协议中的方法

  • (1)Connect。等待与服务器建立连接。
  • (2)Disconnect。等待MQTT客户端完成所做的工作,并与服务器断开TCP/IP会话。
  • (3)Subscribe。等待完成订阅。
  • (4)UnSubscribe。等待服务器取消客户端的一个或多个topics订阅。
  • (5)Publish。MQTT客户端发送消息请求,发送完成后返回应用程序线程。

MQTT如何实现订阅-发布消息模型?

MQTT如何管理连接?

MQTT 是工作在TCP / TLS 协议之上的,是基于连接的,因此在进行主题订阅或消息发布之前,需要先建立连接。MQTT Broker 为了保证网络安全,一般会对请求连接的Client 进行身份验证,因此CONNECT 报文可以携带身份验证信息。MQTT Client 与MQTT Broker 建立连接的过程如下:

MQTT Client 与Broker 建立连接过程
MQTT Client 与Broker 建立连接过程

MQTT如何传递消息?

MQTT 传递消息是基于订阅-发布模型的,Client 与Broker 建立连接后,如果想接收消息,需要先订阅自己感兴趣的主题topic,一个Client 可以订阅多个主题topic。MQTT Client 如果想对外发布消息,消息都需要指定主题topic,Broker 需要通过topic 确定要将该消息分发给哪些Client(MQTT Broker 为每个topic 维护一个订阅者列表)。MQTT Client 向Broker 订阅感兴趣主题topic 的过程如下:

MQTT Client 向Broker 订阅感兴趣主题的流程
MQTT Client 向Broker 订阅感兴趣主题的流程

MQTT 为了适应多种应用场景,支持不同的消息传递服务等级QoS,有些不重要的消息即便对方没有收到也影响不大,有些重要的消息则需要确认对方接收到了。还有些特殊场景,比如支付场景,不仅要求对方确认收到该消息,而且要求该消息的传递是幂等的,也即相同的消息发送多次跟发送一次是一样的结果,不至于出现重复支付的情况。
MQTT Client 取消订阅不感兴趣的主题时,通过UNSUBSCRIBE 报文告知Broker 要取消订阅哪些主题,报文中比较常用的参数是topic。Broker 也会通过UNSUBACK 报文通知Client 取消订阅主题的结果,报文中比较常用的参数是Reason Code。取消订阅的过程和报文格式跟订阅过程类似,这里就不赘述了。

MQTT Client 订阅感兴趣的主题后,如果其它Client 在该topic 上发布消息时,Broker 就可以将该主题上的消息转发给它的订阅者。MQTT Client 在指定主题上发布消息的过程如下:

MQTT Client 向Broker 发布某主题的消息
MQTT Client 向Broker 发布某主题的消息

前面介绍MQTT Client 订阅主题时也指定了QoS,Broker 实际发送给订阅者的消息服务等级还要看消息发布者将消息发送给Broker 的服务等级。也即,Publisher 到Subscribers 传递消息的服务等级等于发布报文中的QoS 和订阅报文中QoS 的最小值。

某个主题的消息从Publisher 经Broker 到Subscribers,采用不同的消息QoS 服务等级,传递消息的报文交互也不同,MQTT 支持的三种QoS 服务等级下,报文的交互过程对比如下:

  • QoS 0 (At most once):Publisher / Broker 只管发布消息,不关心对方是否收到(类似于UDP 协议,没有确认重传机制),QoS 0 的消息发送速率比较高,但消息可能会丢失。常用于对消息丢失不敏感的场景,比如传感器发布状态数据,中间几次数据丢失没关系;
  • QoS 1 (At least once):Publisher / Broker 通过PUBACK 报文确认对方收到了发布的消息,若一段时间内未收到对方的PUBACK 报文则继续重发该消息(重发的消息DUP 标识位设置为1,Packet Identifier 字段值不变),QoS 0 的消息保证对方接收到,但消息可能会重复(Broker / Subscribers 发送PUBACK 报文后再收到相同Packet Identifier 的消息也是按新消息处理的),比如下发给执行器的命令,需要确认命令被响应了;
  • QoS 2 (Exactly once):Publisher / Broker 不仅要通过PUBREC 报文确认对方接收到了发布的消息,还要通过报文PUBREL 和PUBCOMP 的二次交互保证对方接收的消息不重复。这要求接收者Broker / Subscribers 先暂存该消息,等接收到了PUBREL 报文后再将消息递交给上层或转发(消息接收者会忽略PUBLISH 报文中相同Packet Identifier 的消息),QoS 0 的消息对硬件计算存储资源的要求较高、消息延迟也较高,比如在计费支付系统中,每笔订单需要且只能处理一次。

MQTT Quality of Service
MQTT Quality of Service

PUBREC字面意思为Assured publish received,作为订阅者/服务器对QoS level = 2的发布PUBLISH消息的发送方的响应,确认已经收到,为QoS level = 2消息流的第二个消息。 和PUBACK相比,除了消息类型不同外,其它都是一样

PUBREL Qos level = 2的协议流的第三个消息,有PUBLISH消息的发布者发送,参与方接收。

PUBCOMP 作为QoS level = 2消息流第四个,也是最后一个消息,由收到PUBREL的一方向另一方做出的响应消息。完整的消息一览,和PUBREL一致,除了消息类型。

消息接收者Broker / Subscribers 在接收QoS 等级大于0(也即QoS 1 或QoS 2)的消息时,需要在本地暂存该消息(QoS 0 的消息本地不暂存,直接转发或递交给上层应用),QoS 1 的消息需要在本地存储到发送PUBACK 报文后,QoS 2 的消息需要在本地存储到接收PUBREL 报文后。

总结

这只是MQTT的基本理论知识,而更深层的理解需要不断实践。


文章作者: 冬瓜冬瓜排骨汤
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 冬瓜冬瓜排骨汤 !