MQTT 学习笔记

MQTT 学习笔记

MQTT 简介

MQTT (Message Queuing Telemetry Transport,消息队列遥测传输),是IBM 在上个世纪 90 年代退出的一种针对移动终端设备的基于 TCP/IP 的 发布/订阅 协议 。

MQTT IBM 在承接了一个远程监控长距离管道传输的工程时研发的应用层通信协议,这个工程有两个特点:工程距离很长导致设备通信不稳定,由于管道很长带来的传感器数量众多的并发问题。针对这两个问题,IBM 推出了MQTT 通信协议。

MQTT 的特点

  • 可以连接大量的远程传感器和控制设备,MQTT 的特点是可以保持长连接,具有一定的实时性

  • 云端向设备端发送消息,设备端可以在最短的时间内接受到并作出相应

  • MQTT 更适合需要实时控制的场合,尤其适合执行器

  • MQTT 需要保持长连接,解决的方案是时不时地发送心跳包,这样会加大功耗,因此低功耗的场合并不适合 MQTT

  • MQTT 的长连接需要建立在TCP 的基础上,TCP 协议的复杂性决定了对设备的要求比 UDP 更高

  • 使用订阅/发布消息模式,提供一对多的消息发送,解除应用程序耦合

  • 有三种发布服务质量可选,可针对不同情况在可靠性和效率上做出取舍

  • 小型传输,开销很小(固定长度的头部是2 字节),协议交换最小化,以减少网络流量

  • 使用 Last Will(遗嘱) 和 Testament 特性通知有关各方客户端异常

  • 允许用户动态创建主题(类似MQ 的路由),零运维成本

  • 把低带宽、高延迟、不稳定性的网络等因素考虑在内

  • 假设数据不可知,不强求传输数据的类型与格式,保持灵活性

MQTT 解决的问题

  1. 服务器必须要实现成千上万客户端的接入
  2. 单次数据数据量小,但不能出错(准确性)
  3. 必须能够适应高延迟、偶尔断网等通信不可靠的风险
  4. 根据数据的重要程度和特性,设置不同等级的服务质量

MQTT 模型结构

MQTT 主要分为三个部分
  1. MQTT 服务器
  2. 发布者
  3. 订阅者
发布者和订阅者通过服务器上的 主题产生联系,发布者在指定的主题上发布信息,订阅者通过Broker 监听指定的主题获取消息,同时,发布和订阅的关系并不是一成不变的,一个节点可以同时是发布者和订阅者

[图片上传失败...(image-26df1c-1646907042083)]

MQTT Broker

用户可以使用MQTT 构建一个传感器网络,其中 MQTT 代理(服务器)的作用主要就是处理消息从发布程序到订阅程序的转发。

MQTT 服务器除了收集和转发数据,还可以进行数据处理和存储,例如,实时存储共享单车车辆运行位置、电池用量、状态信息等数据,以及对总体的车辆数据进行计算和统筹管理,甚至为一些聊天工具提供平台服务。

MQTT Topic

主题是MQTT 中的一个重要结构,发布和订阅都是通过主题进行的,主题有以下几个特点:
  1. MQTT 通过主题对消息进行分类
  2. 主题本质上就是一个字符串
  3. 主题可以通过 / 表示多个层级关系
  4. 主题并不需要创建,直接使用就行了
  5. 主题支持通过通配符匹配(只能用于订阅,不能用于发布),与MQ 的动态路由类似
    1. + 代表任意一个字符, +/floor-5 可以表示任何一栋楼的五层的设备
    2. * 代表任意 0 个或多个字符, building-b/* 可以表示b楼的所有设备

MQTT 结构(发布/订阅)实现的解耦

  1. 空间解耦
    1. 发布者和订阅者无须了解对方的信息
  2. 时间解耦
    1. 消息可以离线,发布和订阅对时间没有要求
  3. 同步解耦
    1. 发布和解耦都是异步通讯,无须停止任何处理

MQTT 服务质量

为了满足不同的场景,MQTT支持三种不同级别的服务质量(Quality of Service,QoS)为不同场景提供消息可靠性:
  • 级别0:尽力而为。消息发送者会想尽办法发送消息,但是遇到意外并不会重试。

  • 级别1:至少一次。消息接收者如果没有知会或者知会本身丢失,消息发送者会再次发送以保证消息接收者至少会收到一次,当然可能造成重复消息。

  • 级别2:恰好一次。确保消息发送成功一次,保证这种语义肯待会减少并发或者增加延时,不过丢失或者重复消息是不可接受的时候,级别2是最合适的。

    服务质量是个老话题了。级别2 所提供的不重不丢很多情况下是最理想的,不过往返多次的确认一定对并发和延迟带来影响。

MQTT 报文结构

[ Fixed Header 固定报头| Variable Header 可变报头| Payload 有效载荷]

  1. 固定报头:必须存在,用于描述报文信息,比如报文的类型和等级。
  2. 可变报头:可变头部不是可选的意思,而是指这部分在有些协议类型中存在,在有些协议中不存在。
  3. 有效载荷:报文体,有时还会存放一些额外的信息,比如客户ID

Fixed Header

固定报头长度为 `1 Byte`

前 0 - 3 Bit 存放某些报文的特殊标记,4 - 7 Bit 存放 MQTT 报文类型
MQTT 报文类型
MQTT 总共可以表示16种协议类型,其中0000和1111是保留字段。MQTT消息报文类型如下
报文类型 字段值 数据方向 描述
保留 0 禁用 保留
CONNECT 1 Client ---> Server 客户端连接到服务器
CONNACK 2 Server ---> Client 连接确认
PUBLISH 3 Client <--> Server 发布消息
PUBACK 4 Client <--> Server 发不确认
PUBREC 5 Client <--> Server 消息已接收(QoS2第一阶段)
PUBREL 6 Client <--> Server 消息释放(QoS2第二阶段)
PUBCOMP 7 Client <--> Server 发布结束(QoS2第三阶段)
SUBSCRIBE 8 Client ---> Server 客户端订阅请求
SUBACK 9 Server ---> Client 服务端订阅确认
UNSUBACRIBE 10 Client ---> Server 客户端取消订阅
UNSUBACK 11 Server ---> Client 服务端取消订阅确认
PINGREQ 12 Client ---> Server 客户端发送心跳
PINGRESP 13 Server ---> Client 服务端回复心跳
DISCONNECT 14 Client ---> Server 客户端断开连接请求
保留 15 禁用 保留
某些报文的特殊标记
首字节的低4位(bit3~bit0)用来表示某些报文类型的控制字段,实际上只有少数报文类型有控制位,如下
报文类型 固定头标记 Bit 3 Bit 2 Bit 1 Bit 0
CONNECT 保留 0 0 0 0
CONNACK 保留 0 0 0 0
PUBLISH Used in MQTT 3.1.1 DUP QoS QoS RETAIN
PUBACK 保留 0 0 0 0
PUBREC 保留 0 0 0 0
PUBREL 保留 0 0 1 0
PUBCOMP 保留 0 0 0 0
SUBSCRIBE 保留 0 0 1 0
SUBACK 保留 0 0 0 0
UNSUBACRIBE 保留 0 0 1 0
UNSUBACK 保留 0 0 0 0
PINGREQ 保留 0 0 0 0
PINGRESP 保留 0 0 0 0
DISCONNECT 保留 0 0 0 0
**DUP** = 控制报文的重复分发标志
**QoS** = PUBLISH报文的服务质量等级
**RETAIN** = PUBLISH报文的保留标志

QoS用来表明QoS等级,如果Bit 1和Bit 2都为0,表示QoS 0。如果Bit 1为1,表示QoS 1。如果Bit 2为1,表示QoS 2。如果同时将Bit 1和Bit 2都设置成1,那么客户端或服务器认为这是一条非法的消息,会关闭当前连接。

剩余长度

剩余长度  =  可变报头 + 负载数据,长度为 1 - 4 字节,所以一个MQTT 报文的长度最大为5个字节。

剩余长度的大小可变,它是通过将每个字节划分成编码位和延续位来完成的,延续位为每个字节的最高位,如果为1表示下一个字节也是报文内容,如果为 0 表示报文到这个字节为止,不需要往后计算了。
Variable Header
Variable Header的意思是可变化的消息头部。有些报文类型包含可变头部,如PUBLISH,SUBSCRIBE,CONNECT等等。可变头部在固定头部和消息内容之间,其内容根据报文类型不同而不同。

Packet Identifier(消息ID)是一种常见的可变头部,一个消息ID包含2字节,高字节在前,低字节在后。包含Packet Identifier的协议类型包括:
报文类型 包含可变头
PUBLISH YES(QoS > 0)
PUBACK YES
PUBREC YES
PUBREL YES
PUBCOMP YES
SUBSCRIBE YES
SUBACK YES
UNSUBSCRIBE YES
UNSUBACK YES
消息ID默认是从1开始并自增,如果一个消息ID被用完后,这个消息ID可以被重用。对于PUBLISH (QoS 1)来说,如果发送端接收到PUBACK,那么这个消息ID就用完了。对于PUBLISH(QoS 2),如果接收方收到PUBCOMP,那么这个消息ID就用完了。对于SUBSCRIBE和UNSUBSCRIBE,消息ID使用完成的标记是发送方收到了对应的SUBACK和UNSUBACK。
payLoad
消息内容

MQTT 的安装与测试

安装(CentOS 7 +)

  1. 安装软件库(已安装忽略)

    yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
    
  2. 安装 Mosquitto 作为MQTT Borker

    1. 查找

      yum list all | grep mosquitto
      
    image-20220310171451549.png
  1. 安装

    # 一路 yes
    yum install mosquitto.x86_64
    
    image-20220310171644062.png
  1. 启动

    mosquitto
    

测试

订阅
mosquitto_sub -t 
#示例: mosquitto_sub -t test
image-20220310171840283.png
发布
mosquitto_pub -t  -h  -m 
#示例: mosquitto_pub -t test -h localhost -m "hello, world"
image-20220310171938965.png

你可能感兴趣的:(MQTT 学习笔记)