Lazy loaded image
MQTT 协议介绍
Words 2710Read Time 7 min
2024-11-25
 
MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议)是机器对机器(M2M)/物联网(IoT)连接协议。它被设计为一个极其轻量级的发布/订阅消息传输协议。对于需要较小代码占用空间和/或网络带宽非常宝贵的远程连接非常有用,是专为受限设备和低带宽、高延迟或不可靠的网络而设计。这些原则也使该协议成为新兴的“机器到机器”(M2M)或物联网(IoT)世界的连接设备,以及带宽和电池功率非常高的移动应用的理想选择。例如,它已被用于通过卫星链路与代理通信的传感器、与医疗服务提供者的拨号连接,以及一系列家庭自动化和小型设备场景。它也是移动应用的理想选择,因为它体积小,功耗低,数据包最小,并且可以有效地将信息分配给一个或多个接收器[1]。
MQTT is an OASIS standard messaging protocol for the Internet of Things (IoT). It is designed as an extremely lightweight publish/subscribe messaging transport that is ideal for connecting remote devices with a small code footprint and minimal network bandwidth. MQTT today is used in a wide variety of industries, such as automotive, manufacturing, telecommunications, oil and gas, etc. - MQTT - The Standard for IoT Messaging
 
MQTT-SN 协议是 MQTT 的直系亲属,它使用 UDP 进行通信,标准的端口是 1884。MQTT-SN 的主要目的是为了适应受限的设备和网络,比如一些传感器,只有很小的内存和 CPU,TCP 对于这些设备来说非常奢侈。还有一些网络,比如 ZIGBEE,报文的长度在 300 字节以下,无法承载太大的数据包。所以 MQTT-SN 的数据包更小巧。 - MQTT-SN 协议 | EMQX 文档
 

MQTT发布/订阅体系结构

MQTT使用的发布/订阅消息模式,它提供了一对多的消息分发机制,从而实现与应用程序的解耦。这是一种消息传递模式,消息不是直接从发送器发送到接收器(即点对点),而是由MQTT server(或称为 MQTT Broker)分发的。
 

客户端(MQTT Client

指使用 MQTT 的程序或设备,如微控制器(how you can send and receive MQTT messages from devices such as the ESP8266),Raspberry SOC(在树莓派上使用 MQTT | EMQ (emqx.com)),具有 TCP/IP 堆栈和实现 MQTT 协议的计算机程序。客户端总是去连接服务端。它可以
  • 发布其他客户端可能会感兴趣的应用消息
  • 订阅自己感兴趣的的应用消息
  • 退订应用消息
  • 从服务端断开连接
 

服务端(MQTT serverMQTT Broker

扮演订阅或发布应用消息的客户端之间的中间人。可以在Raspberry Pi或 NAS 等单板计算机上实现,也可以在大型机或 Internet 服务器上实现。一个服务端
  • 接受客户端的网络连接
  • 接受客户端发布的应用消息
  • 处理客户端订阅和退订的请求
  • 转发匹配客户端订阅的应用消息
 
 

MQTT 主题/话题和消息

在MQTT中,没有客户端地址和标志符等信息,可以很方便组件拓展自组织网络,客户端唯一需要是服务器地址。客户端订阅发布前无需提前创建,服务器接收任何合格的主题。订阅者和发布者之间信息路由主要是通过主题和消息topics and messages)实现[2]。
 
notion image
  • 发布者发布某一主题消息,如在主题temperature下发布消息28℃
  • 订阅者监听某一主题消息,如所有订阅主题temperature 的订阅者均会收到消息28℃
 
如下翻译自MQTT Essentials - All Core Concepts explained (hivemq.com)系列文章第五节Topics & Best Practices,该章节讨论了MQTT主题命名规范、通配符使用,以及最佳实践内容。

主题命名规范

  • 至少包含一个UTF-8 字符,单独的 “/” 也是合格的主题
  • 大小写敏感 myhome/temperature 和 MyHome/Temperature 为不同的主题
 
multiple topic levels
multiple topic levels

MQTT 通配符

客户端订阅主题信息,可以指定精确的主题名称,也可以使用通配符同时订阅多个主题。而通配符智能用于订阅主题,而不能用于发布主题。通配符分为单层通配符和多层通配符两种。
  • 单层通配符 “+”,只能替换单层主题。如下面例子,单层通配符在第三层,可以随意替换,但其它层的不同则会被过滤。
notion image
notion image
  • 多层通配符 “#”,只能在主题末尾,“/”后面。无论主题有多长,只要通配符前面模式匹配,均会被包括进来。当然,当主题知识单个“#”通配符时,可以接收到发给MQTT的所有消息(只有一个特殊,见下面讲解)。
notion image
notion image
  • 以 “$” 开头的主题,作为服务器内部统计数据,不被包含进入 “#”通配符中,客户端也无法发布消息到这些主题。
     

    最佳实践

    • 不要以“/”开头 Never use a leading forward slash
    • 主题中不要加空格 Never use spaces in a topic
    • 主题应短小精简,尤其对于嵌入式设备Keep the MQTT topic short and concise
    • 避免使用non-ASCII 字符 Use only ASCII characters, avoid non printable characters
    • 添加客户端ID号,增强发布授权 Embed a unique identifier or the Client Id into the topic
    • 需要订阅所有信息保存进数据库场景,避免使用客户端使用通配符处理所有信息,因为客户端往往难以处理如此大负担,plugin system of HiveMQ 插件实现服务器处理所有进入的数据。 Don’t subscribe to #
    • 需考虑主题的拓展性 Don’t forget extensibility
    • 主题尽量明确,而非通用主题,便于MQTT其他功能。如有三个传感器myhome/livingroom/temperaturemyhome/livingroom/brightnes 和myhome/livingroom/humidity比单独用一个主题myhome/livingroom包含三个传感器值更好。 Use specific topics, not general ones
     

    服务质量 QoS(Quality of Service levels)

    如下翻译自MQTT Essentials - All Core Concepts explained (hivemq.com)系列文章第六节Quality of Service (QoS) 0,1, & 2 MQTT Essentials: Part 6 (hivemq.com),该章节讨论了MQTT中 Quality of Service (QoS)等级特点、注意事项,以及最佳实践内容。
    服务质量是 MQTT 的一个重要特性。当我们使用 TCP/IP 时,连接已经在一定程度上受到保护。但是在无线网络中,中断和干扰很频繁,QoS 可根据网络状况和应用逻辑,灵活设置,以避免信息丢失和保证服务质量水平。定义的级别在发布时使用。
    信息收发分为两种,且两者之间有细微差别
    1. 如果客户端发布到 MQTT 服务器,则客户端将是发送者,MQTT 服务器将是接收者。
    1. 当MQTT服务器向客户端发布消息时,服务器是发送者,客户端是接收者。
    对于第一种,QoS是由客户端发送数据到服务器时定义的;而对第二种,QoS实在订阅客户端订阅时定义的。假如订阅客户端QoS等级低于发布客户端,服务器以较低等级发布数据(Downgrade of QoS)。
     

    等级

    QoS 0 - at most once
    • 发送后无确认,不重发
    • 又称“fire and forget”
    • 消息发布依赖于底层TCP/IP网络
    Quality of Service level 0: delivery at most once
    Quality of Service level 0: delivery at most once
    notion image
    QoS 1 - at least once
    • 保证最少传输一次
    • 接收端接收后发送 “PUBACK” 确认包,发送端若为接收到,会重发数据
    • 若数据重复发送两次,DUP标志置位,处理器和客户端不处理重复数据
    Quality of Service level 1: delivery at least once
    Quality of Service level 1: delivery at least once
    notion image
    QoS 2 - exactly once
    • 四次握手,至少两次请求/响应数据流
    • 最安全也是开销最大,传输最慢的一种
    Quality of Service level 2: delivery exactly once
    Quality of Service level 2: delivery exactly once
    notion image

    最佳实践

    Use QoS 0 when …
    • 收发连接稳定,比如有线连接
    • 数据发送间隔小,数据丢失可接受
    • 无需使用消息队列
    Use QoS 1 when …
    • 需要收到每个数据
    • 应用场景可以接受数据重复,并可以处理
    • 无法接受 QoS 2 的高负载
    Use QoS 2 when …
    • 所有数据只能严格接收一个
    • 重复发送不可接受

    MQTT 特点

    • 开放消息协议,简单易实现
    • 发布订阅模式,一对多消息发布
    • 基于TCP/IP网络连接,提供有序,无损,双向连接(服务器到客户端,客户端到服务器),广播信息方便。
    • 1字节固定报头,2字节心跳报文,最小化传输开销和协议交换,有效减少网络流量。
    • 支持消息 QoS ,持续对话,减少重连耗时,保证可靠传输
    关于MQTT的设计规范和主要特性还可参考MQTT 入门介绍 | 菜鸟教程 (runoob.com)

    MQTT服务器搭建

    目前MQTT代理的主流平台有下面几个:
     
    Eclipse Mosquitto is an open source (EPL/EDL licensed) message broker that implements the MQTT protocol versions 5.0, 3.1.1 and 3.1. Mosquitto is lightweight and is suitable for use on all devices from low power single board computers to full servers.
    Eclipse mosquito是一个开源消息服务器(EPL/EDL许可),实现了MQTT协议版本5.0、3.1.1和3.1。mosquito是轻量级的,适用于所有设备,从低功耗单板计算机到完整的服务器。
    The Mosquitto project also provides a C library for implementing MQTT clients, and the very popular mosquitto_pub and mosquitto_sub command line MQTT clients.
    mosquito to项目还提供了一个用于实现MQTT客户机的C库,以及非常流行的mosquito to_pub和mosquito to_sub命令行操作。
     
     
    上一篇
    Data Structure and Algorithm
    下一篇
    用面试拷问嵌入式技术栈

    Comments
    Loading...