欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~

翻译人:Tnecesoc,该成员来自云+社区翻译社

消息队列遥测传输(MQTT)是一种客户端服务器发布 / 订阅消息传输协议。它轻量,开放,简单,其设计也易于实施。这些特性使其非常适合用于很多情况,包括在网络连接受限的,需要代码长度较小且 / 或网络带宽非常重要的环境里面,例如在机器对机器(M2M)和物联网(IoT)环境中的通信。该协议通过 TCP / IP 或其他能提供有序,无损,双向的连接的网络协议运行。

MQTT支持三种服务质量级别,如上图所示:

  1. 最多发送一次(发完就忘),也就是不确认

  2. 至少发送一次,需要进行确认

  3. 正好发送一次,要进行 4 步握手

QoS(服务质量)定义了服务端(Broker) / 客户端(Client)确保能收到消息的工作或尝试的方式。消息可以以任何 QoS 级别发送,客户端也可以选择以任意 QoS 级别来订阅主题,后者选择的是他们能收到的最高 QoS 级别。

例如,如有消息以 QoS 2 级别发布并且有一客户端以 Qos 0 级别订阅了相应主题,则那一客户端就会以 QoS 0 级别收到该消息。如果有第二个客户端也订阅了相同的主题,但用的是 QoS 2,则它将以 QoS 2 级别收到这一消息。

举另外一个例子,如有一客户端以 QoS 2 订阅了一个主题,并且有一消息以 QoS 0 在相应主题上发布,则客户端将会基于 QoS 0 级别接收这一消息。高级的 QoS 会更可靠,但也会带来更高的延迟,并占用更多的带宽。

每个 QoS 级别的一些细节就如下所示。MQTT 控制数据包内容的表格位于本文的最后部分,用于描述来自每个 QoS 流的控制数据包。

服务质量级别 0

该消息最多只发送一次,或者在通过网络的传送受阻的时候根本不发送。发送的消息不会被保存。如果客户端断开了连接,或者服务端出现了故障,该消息可能就会因此丢失。这也是最快的传输模式。MQTT 协议并没有要求服务器端将 QoS = 0 的发布消息转发给客户端。如果客户端在服务器收到发布的消息时断开了连接,则发布的消息可能会被丢弃,具体取决于服务器。遥测(MQXR)服务不会丢弃以 QoS = 0 发送的消息。它们会被作为非持久消息而保存,且只有在队列管理器停止运作时才会被丢弃。

在 QoS 0 传送协议中:

  • 发送者:必须发送 QoS = 0,DUP = 0 的 PUBLISH 包;

  • 接收者:在接收到 PUBLISH 包的同时也接受消息的所有权。

服务质量级别 1

该消息至少发送一次。如果发送方没有收到确认包,则会再次发送加上 DUP 标志的该消息,直到收到确认包为止。因此,接收者可能会把相同的消息发送好几次,并且也可能把它处理了好几遍。消息必须保存在发送者以及接收者的本地环境里面,直到这一消息被妥善处理为止。接收者在处理完消息后会把消息删掉。如果接收者是个服务端,则它会将把该消息发布给其订阅者作为对消息的处理。如果接收者是客户端,则会将把消息传递给作为订阅者的应用程序作为处理。在消息被删除之后,接收方会向发送方发送确认包。发送方在收到接收方的确认后会删掉保存在发送方的消息。

这个级别可以用于传送例如环境传感器这样的数据。在这种情况下,单个读数的传送失败了也没多大关系,因为传感器很快就会再把读数发送一遍。

在 QoS 1 传送协议中:

  • 发送方:

    • 必须在每次有新的应用消息发布时为其分配一个没被占用的包标识符。

    • 必须发送一个 PUBLISH 包,其中包含 QoS = 1,DUP = 0 的包标识符。

    • 必须将 PUBLISH 数据包视为 “未经确认” 的,直到它收到了接收方发来的,相应的 PUBACK 数据包为止。

    • 一旦发送者收到 PUBACK 包,对应的消息的包标识符就能收回并重用。请注意,当发送方正在等待接收确认时,它可以用不同的包标识符发送更多的 PUBLISH 包。

  • 接收方:

    • 在接受了应用消息的所有权后,必须用包含传入 PUBLISH 包的包标识符的 PUBACK 包来进行响应。

    • 在发送 PUBACK 包后,接收方必须把每一个传入的包含相同包标识符 PUBLISH 包视为一个全新的发布消息,而不管这些发布消息有没有加上 DUP 标志。

服务质量级别 2

该消息始终只发送一次。消息必须存储在发送方和接收方的本地环境中,直到它被妥善处理为止。QoS = 2 是最安全但也是最慢的传输模式。从发送方删掉消息之前,发送方和接收方之间至少需要两次相互的传输。在第一次传输后,接收方就可以开始处理这一消息。在第一次互传中,发送方会发送消息并从接收方拿到对这一消息的确认。如果发送方没有收到确认,则会再次发送加上了 DUP 标志的该消息,直至收到确认。在第二次互传中,发送方通过给接收方发送 PUBREL 消息来告知后者它可以完成对发布的消息的处理了。如果发送方没有收到接收方对 PUBREL 消息的确认,则会把 PUBREL 消息再发一遍,直到收到确认为止。当发送者收到对 PUBREL 消息的确认时,发送者就会删掉它保存的消息。接收者可以在第一或第二次互传的时候处理消息,只要它不把消息又重新处理一遍就可以了。如果接收者是服务端,它会将消息发布给订阅者。如果接收方是客户端,它会将消息传递给作为订阅者的应用程序。最后接收方会向发送方发送处理完成的消息,来表明它已完成了消息的处理。

举例来说,计费系统可以使用这个级别,因为消息的重复或丢失会导致这样的应用产生错误的计费。

在 QoS 2 传送协议中:

  • 发送方:

    • 必须在每次有新的应用消息发布时为其分配一个没被占用的包标识符。

    • 必须发送一个包含 QoS = 2,DUP = 0 的包标识符的 PUBLISH 包。

    • 必须将 PUBLISH 数据包视为 “未经确认” 的,直到它收到了接收方发来的,相应的 PUBREC 数据包为止。

    • 当它从接收器收到一个 PUBREC 包时,必须发送一个 PUBREL 包。这个 PUBREL 包应该包含与原始 PUBLISH 分组相同的包标识符。

    • 必须将 PUBREL 数据包视为 “未经确认” 的,直到它从接收方收到了相应的 PUBCOMP 包为止。

    • 一旦发送了相应的 PUBREL 包,发送方就不能再发送原始的 PUBLISH 包。一旦发送者收到 PUBCOMP 包,包标识符就可以收回并重用。注意,当发送方正在等待接收确认时,它可以使用不同的包标识符发送更多的 PUBLISH 包。

  • 接收方:

    • 在接受了 PUBLISH 包的应用消息的所有权后,必须用包含传入 PUBLISH 包的包标识符的 PUBREC 包来进行响应。

    • 在接收方收到相应的 PUBREL 包之前,它必须对每一个具有和传入 PUBLISH 包相同包标识符的后续 PUBLISH 包发送一个 PUBREC 包来进行确认。它绝不能容许把一个内容重复的消息传给任何位于下游的接收方。

    • 在收到发送方发来的 PUBREL 包之后,它必须通过发送包含与 PUBREL 相同的包标识符的 PUBCOMP 包来响应。

    • 发送 PUBCOMP 包后,接收方必须把任何后续的具有与传入 PUBLISH 包相同包标识符的后续 PUBLISH 包视为全新的发布消息。

MQTT 控制数据包的详述

控制包 发送方向 描述
CONNECT 客户端 -> 服务端 客户端请求与服务端建立连接
CONNACK 服务端 -> 客户端 连接成功建立
PUBLISH 客户端 -> 服务端 / 服务端 -> 客户端 发布消息
PUBACK 客户端 -> 服务端 / 服务端 -> 客户端 收到发布消息的确认
PUBREC 客户端 -> 服务端 / 服务端 -> 客户端 收到发布消息(Qos 2 的第二次握手)
PUBREL 客户端 -> 服务端 / 服务端 -> 客户端 不再发布消息(Qos 2 的第三次握手)
PUBCOMP 客户端 -> 服务端 / 服务端 -> 客户端 消息发布的完结(Qos 2 的第四次握手)
SUBSCRIBE 客户端 -> 服务端 客户端请求订阅某主题
SUBACK 服务端 -> 客户端 订阅操作成功
UNSCBSCRIBE 客户端 -> 服务端 客户端请求取消订阅某主题
UNSCBACK 服务端 -> 客户端 取消订阅操作成功
PINGREQ 客户端 -> 服务端 PING 请求
PINGRESP 服务端 -> 客户端 PING 响应
DISCONNECT 客户端 -> 服务端 客户端断开了与服务端的连接

参考文献

OASIS 文档:

有些内容转自 BB Smartworx 和 IBM Developer Work。

本文的版权归 Tnecesoc 所有,如需转载请联系作者。


问答

物联网技术在智慧城市中应用难点与疑点?

NB-IOT技术全面商用后的前景如何?如何部署和开发?

相关阅读

启动物联网项目所需的一切

物联网是如何加强普适计算的

物联网 MQTT 服务质量级别的更多相关文章

  1. 物联网MQTT协议分析和开源Mosquitto部署验证

    在<物联网核心协议—消息推送技术演进>一文中已向读者介绍了多种消息推送技术的情况,包括HTTP单向通信.Ajax轮询.Websocket.MQTT.CoAP等,其中MQTT协议为IBM制定 ...

  2. Paho -物联网 MQTT C Cient的实现和详解

    概述   在文章Paho - MQTT C Cient的实现中,我介绍了如何使用Paho开源项目创建MQTTClient_pulish客户端.但只是简单的介绍了使用方法,而且客户端的结果与之前介绍的并 ...

  3. 纯vue3实现的svg可视化web组态编辑器。主要用于物联网mqtt实时系统图

    vue就是边做这个项目边学的 代码可能有点乱 还望各位大神勿喷 如果代码对您有帮助 麻烦辛苦帮我点个star 预览地址 https://svg.yaolunmao.top 如何使用 # 克隆项目 gi ...

  4. MQTT物联网通讯协议入门

    目录 一.MQTT协议概念 发布/订阅机制 MQTT客户端 Broker代理(服务器) MQTT消息结构 二.MQTT协议实现原理 MQTT连接 MQTT消息发布 MQTT订阅机制 MQTT订阅确认 ...

  5. 转战物联网·基础篇06-深入理解MQTT协议之基本术语

      通过上一节我们对MQTT协议已经有了初步的印象,这一节我们开始深入的理解一下MQTT协议,介绍常用的MQTT 3.1.1版本,5.0版本后面指介绍新增部分即可.这一节我们先介绍MQTT里常用的术语 ...

  6. MQTT初始篇笔记整理

    MQTT简介 MQTT(Message Queuing Telemetry Transport,消息队列遥测传输),基于TCP/IP 协议栈而构建,虽然叫消息队列遥测传输,但是她与消息队列毫无关系,她 ...

  7. 基于 WebSocket 的 MQTT 移动推送方案

    WebSphere MQ Telemetry Transport 简介 WebSphere MQ Telemetry Transport (MQTT) 是一项异步消息传输协议,是 IBM 在分析了他们 ...

  8. 国外物联网平台(3):IBM Watson IoT

    国外物联网平台(3)——IBM Watson IoT 马智 平台定位 提供全面管理的云托管服务,旨在简化并从 IoT 设备中获得价值. Watson IoT Platform 提供对 IoT 设备和数 ...

  9. MQTT 协议是个啥?这篇文章告诉你!

    文章首发于我的公众号「程序员cxuan」,欢迎大家关注呀- 说到做到! 之前有位读者给我留言说想要了解一下什么是 MQTT 协议,顺便还把我夸了一把,有点不好意思啦. 那么读者的要求必须要满足啊,所以 ...

随机推荐

  1. Linux运维主流架构简单剖析

    随着IT运维的不断发展,尤其的Linux的飞速发展,越来越多的企业开始使用Linux操作系统平台,例如CentOS.RedHat.Ubuntu.Fedora等等,成千上亿个网站涌现在当今互联网,互联网 ...

  2. Jmeter 前置处理器 BeanShell_PreProcessor 适用思考

    首先摘抄一段官方文档的话: Before invoking the script, some variables are set up in the BeanShell interpreter: lo ...

  3. echarts对每个data[i]的图片添加点击事件

    1.综述:以饼图为例,只需要对echarts对象option添加以下几行代码即可 //添加点击事件(单击),还有其他鼠标事件和键盘事件等等 myChart1.on("click", ...

  4. LeetCode-391. 完美矩形(使用C语言编译,详解)

    链接:https://leetcode-cn.com/problems/perfect-rectangle/description/ 题目 我们有 N 个与坐标轴对齐的矩形, 其中 N > 0, ...

  5. C语言博客作业—字符数组

    一.PTA实验作业 题目1:字符串转换成十进制整数 1. 本题PTA提交列表 2. 设计思路 (1)定义i为循环变量,number用于存放每一次转化的结果,flag用于判断是否为负数,p用于修改结果的 ...

  6. 【Swift】iOS裁剪或者压缩后出现的白边问题

    只需要将所有的CGFloat转化为NSInteger即可 func imageScaleSize(newSize: CGSize) -> UIImage{ let width = NSInteg ...

  7. verilog学习笔记(0)

    assign赋值语句根本不允许出现在always语句块中 位于begin/end块内的多条阻塞赋值语句是串行执行的; 但是多条非阻塞赋值语句却是并行执行的,这些非阻塞赋值语句都会在其中任何一条语句执行 ...

  8. JavaScript 相关知识

    一.数组   var a = [1,2,3,4]; console.log(a.length); a.push(5); console.log(a); // [1, 2, 3, 4, 5] var r ...

  9. DML数据操作语言之常用函数

    所谓函数,就是输入某一值,得到相应的输出结果的功能.相当于一个加工厂,给了原料,最终产出成品. 其中原料 就是参数(parameter). 产品 就是返回值. 函数大致可以分为以下五个种类: 算术函数 ...

  10. Packet for query is too large (84 > -1).

    windows下的resin配置连接mysql,常用的安全的做法是将数据库信息配置到conf目录下的resin.xml文件中. 因为resin连接mysql不是必须的,所以resin本身没有提供mys ...