物联网协议之MQTT

简介: 物联网协议之MQTT

MQTT

简介

MQTT 可以简单看做一个网络协议,用于机器对机器的通信(与客户端到服务器的传输有点区别)。智能传感器、可穿戴设备和其他物联网(IoT)设备通常必须通过带宽有限资源受限网络传输和接收数据。这些物联网设备使用 MQTT 进行数据传输,因为它易于实施,并且可以有效地传输物联网数据。MQTT 支持设备到云端和云端到设备之间的消息传递。

特点

  1. 轻量级:MQTT协议是一种轻量级的协议,它的开销非常小,可以在低带宽、不稳定的网络环境下运行。
  2. 灵活性:双向通信,MQTT协议支持多种消息传输模式,包括点对点、发布/订阅和请求/响应等模式,可以根据不同的应用场景选择合适的模式。
  3. 可靠性:MQTT协议支持QoS(服务质量)等级,可以确保消息的可靠传输,同时还支持消息持久化和重传机制,保证消息不会丢失。
  4. 易于集成:MQTT协议可以与各种不同的平台和设备集成,包括传感器、嵌入式设备、移动设备和云平台等,可以实现跨平台、跨设备的通信。
  5. 安全性:MQTT协议支持TLS/SSL加密和认证机制,可以保证消息的安全传输和身份验证,防止数据泄露和攻击。

MQTT为什么轻量

从连接角度上看

HTTP:假设有一个传感器设备需要定期向云平台发送数据,数据量很小,只有几个字节,但是设备的网络带宽很低,且网络连接不稳定。如果使用传统的HTTP协议来传输数据,由于HTTP协议的开销较大,每次传输都需要建立TCP连接、发送HTTP头部等操作,会导致网络带宽的浪费和连接的不稳定性

MQTT:而如果使用MQTT协议来传输数据,由于MQTT协议是一种轻量级的协议,它的开销非常小。1.只需要建立一次TCP连接,然后就可以通过MQTT协议来传输数据,不需要每次都重新建立连接和发送头部信息,可以大大减少网络带宽的浪费和连接的不稳定性。2.同时,MQTT协议还支持QoS等级,可以确保数据的可靠传输,即使网络连接不稳定,也可以保证数据不会丢失。

MQTT的长连接机制和HTTP的Keep-Alive机制有所不同,HTTP中客户端和服务器之间的数据传输是同步的。MQTT客户端和服务器之间的数据传输是异步的,客户端可以发送多个消息,服务器可以异步地接收和处理这些消息。需要注意的是,MQTT协议的长连接机制需要客户端和服务器之间的协作,客户端需要定期发送心跳包来保持连接,服务器需要及时响应心跳包,以保证连接的稳定性。同时,长时间的连接也会占用服务器的资源,因此需要合理设置连接的超时时间和心跳包的发送间隔。

从报文角度上看

  1. MQTT协议的头部信息

MQTT协议的头部信息非常简单,只需要几个字节就可以表示。MQTT协议的头部信息包括以下几个字段:

  • 固定头部:包含消息类型、QoS等级、保留标志等信息,共1个字节。
  • 可变头部:包含消息标识符、主题名等信息,长度不固定。
  • 消息体:包含消息的实际内容,长度不固定。

例如:假设有一个MQTT客户端需要向服务器发送一条消息,消息内容为"Hello, MQTT!“,主题名为"test”,QoS等级为1。

固定头部:0x32(消息类型为Publish,QoS等级为1,保留标志为0)

可变头部:0x00 0x04(主题名长度为4)

主题名:0x74 0x65 0x73 0x74(主题名为"test")

消息标识符:0x00 0x01(消息标识符为1)

消息体:0x48 0x65 0x6C 0x6C 0x6F 2C 0x20 0x4D 0x51 0x54 0x54 0x21(消息内容为"Hello, MQTT!")

  1. HTTP协议的头部信息

HTTP协议的头部信息相对复杂,包含了很多字段,主要用于描述请求或响应的相关信息。HTTP协议的头部信息包括以下几个部分:

  • 请求行:包含请求方法、请求URL和HTTP协议版本等信息。
  • 请求头部:包含请求的附加信息,如请求头部字段、Cookie等。
  • 空行:用于分隔请求头部和请求正文。
  • 响应行:包含HTTP协议版本、状态码和状态描述等信息。
  • 响应头部:包含响应的附加信息,如响应头部字段、Cookie等。
  • 空行:用于分隔响应头部和响应正文。
  • 响应正文:包含响应的实际内容,长度不固定。

例如:

假设有一个HTTP客户端需要向服务器发送一个GET请求,请求URL为"http://www.example.com/index.html",请求头部包含"User-Agent"和"Accept-Language"字段。那么该请求的HTTP协议头部信息如下:

请求行:GET /index.html HTTP/1.1

请求头部: User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 Accept-Language: en-US,en;q=0.8

空行:

响应行:HTTP/1.1 200 OK

响应头部: Content-Type: text/html; charset=UTF-8 Content-Length: 1234

空行:

响应正文:(省略)

可以对比看出MQTT协议的报文信息都是用十六进制表示,各个请求属性也是这种用二进制的位图去区分,相对HTTP报文都是字符串来说更加的轻量,节省传输资源。

从数据类型上看

HTTP协议的数据格式是文本格式,即使用ASCII码表示的文本字符串,而MQTT协议的数据格式是二进制格式,即使用字节流表示的二进制数据。

使用二进制表示的话,每个字节可以表示多个0或1,而文本字符串使用字符编码方式表示,每个字符通常需要使用多个字节来表示,例如UTF-8编码中的中文字符需要使用3个字节来表示,这就导致了文本字符串的数据大小通常比二进制数据大。

同时二进制数据通常可以使用压缩算法进行压缩,压缩后的数据大小更小,传输效率更高。而文本字符串的压缩效果通常不如二进制数据,因为文本字符串中的字符通常是不规则的,难以进行有效的压缩。

总的来说,使用二进制数据传输可以减少数据的大小,提高传输效率,因为二进制数据使用二进制编码方式表示,可以更紧凑地表示数据,同时可以使用更高效的压缩算法进行压缩,而且二进制数据通常使用二进制传输方式,传输效率更高。与之相比,文本字符串的数据大小通常较大,压缩效果较差,传输效率较低。

三种服务质量

MQTT的三种服务质量及实现原理:

https://www.emqx.com/zh/blog/introduction-to-mqtt-qos

QoS 0:最多一次传递

在QoS 0级别下,发布者只需将消息发送给MQTT代理,代理会将消息发送给订阅者,但不会保证消息是否到达订阅者。这种级别的实现非常简单,因为不需要进行确认或重传,所以消息传递的延迟和带宽占用都很低。

通常选择使用 QoS 0 传输一些高频且不那么重要的数据,比如传感器数据,周期性更新,即使遗漏几个周期的数据也可以接受。

QoS 1:最少一次传递

发送方发送报文后,需要收到一个ACK报文,才会停止重复发送,否则到了超时时间会重传报文。这里其实是涉及到两次网络传输(一次发送报文消息、一次接收方发送ACK报文信息)

在QoS 1级别下,发布者将消息发送给MQTT代理,代理会将消息发送给订阅者,并等待订阅者的确认。如果代理没有收到确认,它会重新发送消息,直到收到确认为止。这种级别的实现需要进行确认和重传,所以消息传递的延迟和带宽占用都比QoS 0高。

QoS1在协议层面上无法避免消息重复的情况,因此在我们的报文内容里面通常加上报文的唯一id,在应用层通过id去对消息去重是最常规的处理方法。

QoS 2:恰好一次传递

前提:MQTT识别报文是通过一个Packet ID来识别是不是重复信息。Qos1收到两条相同Packet ID报文的消息是没办法知道这是重复的信息,还是两条不同的消息只是用的同一个ID的情况,因此Qos1是存在重复消息的问题。QoS2会用更加复杂的交互逻辑来确保消息不会重复。

发送方发送完报文,需要等待收到接收方发送PUBREC报文(在这期间还可以超时重发这个报文),等到收到PUBREC报文后,发送方会继续发送PUBREL (Publish Release)报文,此时不能再重发报文了,并且Packet ID也不能使用。等待收到对端回复的 PUBCOMP 报文后,才表示此时Packet ID被释放完成,可以继续使用Packet ID去发送消息。

因此对于接收方以 PUBREL 报文为界限,凡是在 PUBREL 报文之前到达的 PUBLISH 报文,有相同的Packet ID都必然是重复的消息;而凡是在 PUBREL 报文之后到达的 PUBLISH 报文,有相同的Packet ID都必然是全新的消息。

在QoS 2级别下,发布者将消息发送给MQTT代理,代理会将消息发送给订阅者,并等待订阅者的确认。如果代理没有收到确认,它会重新发送消息,直到收到确认为止。订阅者收到消息后,会发送确认给代理,代理再将确认发送给发布者。如果代理没有收到确认,它会重新发送消息,直到收到确认为止。这种级别的实现需要进行确认、重传和去重,所以消息传递的延迟和带宽占用都比QoS 1更高。

总的来说,QoS级别越高,消息传递的可靠性越高,但延迟和带宽占用也越高。在选择QoS级别时,需要根据应用场景的需求来进行权衡。

在MQTT中,QoS级别是在发布消息时指定的。接收者也可以指定所需的QoS级别。如果发布者和接收者的QoS级别不同,MQTT会自动升级到更高的级别。例如,如果发布者使用QoS 0,而接收者使用QoS 2,MQTT会将消息升级到QoS 2级别。

消息可靠

MQTT还有一个持久会话的功能,对应的是Clean Session(清理会话)选项。当Clean Session = 0,以及QoS为1或着2的时候,加入接收端离线了也会在下次在线时收到断连期间的消息。此时的消息会暂存在我们的MQTT服务器端。

MQTT Broker

MQTT Broker 也称为 MQTT 消息服务器,它可以是运行了 MQTT 消息服务器软件的一台服务器或一个服务器集群。

MQTT Broker 负责接收来自客户端的网络连接,并处理客户端的订阅/取消订阅、消息发布(Publish)请求,同时也会将客户端发布的消息转发给其他订阅者。

MQTT负载均衡

MQTT通过共享订阅的方式来做订阅端的负载均衡

MQTT使用共享订阅来实现负载均衡的方法如下:

  1. 创建一个共享订阅,多个客户端可以订阅同一个主题。
  2. 在共享订阅中,MQTT服务器将消息平均分配给所有订阅者,以实现负载均衡。
  3. 当一个客户端订阅了共享订阅中的主题时,它将收到一部分消息。
  4. 如果有多个客户端订阅了共享订阅中的主题,它们将共享消息的负载。
  5. 如果一个客户端断开连接,MQTT服务器将重新分配该客户端的负载给其他订阅者。
  6. 使用共享订阅可以提高MQTT服务器的性能和可伸缩性,同时确保消息的可靠传递。

例如实时数据处理:当需要处理大量实时数据时,使用共享订阅可以将数据平均分配给多个订阅者,从而实现负载均衡。

MQTT broker也可以通过集群实现服务器端的负载均衡

多服务器节点集群,且支持节点的自动发现。相对于单服务器,集群能通过多台服务器之间的协作带来以下优势:

  • 高可用性。单台或少量的服务器故障并不会导致整个消息服务中断,其余的正常工作的节点可以继续提供服务;
  • 负载均衡。通过负载均衡机制,集群可以把负载平均的分布在各个节点;
  • 更高的整体性能。相比单机部署,多节点的集群能够成倍的提升整个系统的连接和消息处理能力;
  • 可扩展性。可以通过在集群中添加新节点的方式来完成扩容而无需停机。

MQTT做请求应答模式

MQTT本身是一种发布/订阅模式的通信协议,不直接支持请求/响应模式。但是,可以通过以下方法实现请求/响应模式:

  1. 使用MQTT的QoS(服务质量)机制。将QoS设置为1或2,可以确保消息的可靠传输和确认。在请求消息中设置一个唯一的标识符,然后在响应消息中包含相同的标识符,以便请求方可以识别响应。 2. 使用专门的主题来处理请求和响应。例如,可以使用“request”主题来发送请求消息,然后使用“response”主题来发送响应消息。请求方可以订阅响应主题,以便在收到响应时进行处理。
  2. 使用MQTT的遗嘱消息机制。请求方可以在发送请求消息时设置遗嘱消息,以便在请求方离线或者异常时,服务器可以代替请求方给所有订阅相关主题的客户端发送一个响应消息作为遗嘱消息。

需要注意的是,使用MQTT实现请求/响应模式可能会增加通信的延迟和复杂性。因此,应该根据具体的应用场景和需求来选择合适的通信模式。

相关实践学习
阿里云AIoT物联网开发实战
本课程将由物联网专家带你熟悉阿里云AIoT物联网领域全套云产品,7天轻松搭建基于Arduino的端到端物联网场景应用。 开始学习前,请先开通下方两个云产品,让学习更流畅: IoT物联网平台:https://iot.console.aliyun.com/ LinkWAN物联网络管理平台:https://linkwan.console.aliyun.com/service-open
目录
相关文章
|
6月前
|
消息中间件 安全 物联网
海量接入、毫秒响应:易易互联基于 Apache RocketMQ + MQTT 构筑高可用物联网消息中枢
易易互联科技有限公司是吉利集团旗下专注于换电生态的全资子公司,致力于打造安全、便捷、便宜的智能换电网络。公司依托吉利GBRC换电平台,基于电池共享与车辆全生命周期运营,已布局超470座换电站,覆盖40多个城市,计划2027年达2000座。面对海量设备高并发连接、高实时性要求及数据洪峰挑战,易易互联采用阿里云MQTT与RocketMQ构建高效物联网通信架构,实现稳定接入、低延迟通信与弹性处理,全面支撑其全国换电网络规模化运营与智能化升级。
412 1
海量接入、毫秒响应:易易互联基于 Apache RocketMQ + MQTT 构筑高可用物联网消息中枢
|
6月前
|
数据采集 传感器 监控
Modbus 与 MQTT 协议兼容:MyEMS 的泛在能源数据采集技术实现
MyEMS深度融合Modbus与MQTT协议,破解能源数据采集中协议碎片化、网络异构、数据孤岛等难题。通过Modbus接入95%以上工业设备,实现现场数据精准“拉取”;依托MQTT构建高效物联网传输通道,支持多源数据主动“推送”与云端集成。边缘侧采集规整,中心侧汇聚分析,形成统一、可靠、低延迟的数据流。该架构兼具高兼容性、强扩展性与低运维成本,广泛应用于工业园区、商业楼宇及集团型企业,支撑实时监控、AI分析与跨系统融合,打造泛在互联的能源数据底座,助力企业实现全面智慧能源管理。
450 6
|
11月前
|
数据采集 监控 网络协议
​MCP协议深度解析:原理、应用与物联网时代的机遇-优雅草卓伊凡
​MCP协议深度解析:原理、应用与物联网时代的机遇-优雅草卓伊凡
1233 40
​MCP协议深度解析:原理、应用与物联网时代的机遇-优雅草卓伊凡
|
10月前
|
物联网
(手把手)在华为云、阿里云搭建自己的物联网MQTT消息服务器,免费IOT平台
本文介绍如何在阿里云搭建自己的物联网MQTT消息服务器,并使用 “MQTT客户端调试工具”模拟MQTT设备,接入平台进行消息收发。
3213 42
|
10月前
|
物联网
如何在腾讯云等平台搭建自己的物联网MQTT服务器Broker
物联网技术及MQTT协议被广泛应用于各种场景。本文介绍物联网MQTT服务助手下载,如何搭建自己的物联网平台,并使用 “MQTT客户端调试工具”模拟MQTT设备,接入平台进行消息收发。
751 37
|
9月前
|
监控 安全 Java
Java 开发中基于 Spring Boot 3.2 框架集成 MQTT 5.0 协议实现消息推送与订阅功能的技术方案解析
本文介绍基于Spring Boot 3.2集成MQTT 5.0的消息推送与订阅技术方案,涵盖核心技术栈选型(Spring Boot、Eclipse Paho、HiveMQ)、项目搭建与配置、消息发布与订阅服务实现,以及在智能家居控制系统中的应用实例。同时,详细探讨了安全增强(TLS/SSL)、性能优化(异步处理与背压控制)、测试监控及生产环境部署方案,为构建高可用、高性能的消息通信系统提供全面指导。附资源下载链接:[https://pan.quark.cn/s/14fcf913bae6](https://pan.quark.cn/s/14fcf913bae6)。
1988 0
|
8月前
|
消息中间件 数据管理 Serverless
阿里云消息队列 Apache RocketMQ 创新论文入选顶会 ACM FSE 2025
阿里云消息团队基于 Apache RocketMQ 构建 Serverless 消息系统,适配多种主流消息协议(如 RabbitMQ、MQTT 和 Kafka),成功解决了传统中间件在可伸缩性、成本及元数据管理等方面的难题,并据此实现 ApsaraMQ 全系列产品 Serverless 化,助力企业提效降本。
|
6月前
|
消息中间件 Java Kafka
消息队列比较:Spring 微服务中的 Kafka 与 RabbitMQ
本文深入解析了 Kafka 和 RabbitMQ 两大主流消息队列在 Spring 微服务中的应用与对比。内容涵盖消息队列的基本原理、Kafka 与 RabbitMQ 的核心概念、各自优势及典型用例,并结合 Spring 生态的集成方式,帮助开发者根据实际需求选择合适的消息中间件,提升系统解耦、可扩展性与可靠性。
440 1
消息队列比较:Spring 微服务中的 Kafka 与 RabbitMQ
|
消息中间件 JSON Java
开发者如何使用轻量消息队列MNS
【10月更文挑战第19天】开发者如何使用轻量消息队列MNS
999 93
|
消息中间件 安全 Java
云消息队列RabbitMQ实践解决方案评测
一文带你详细了解云消息队列RabbitMQ实践的解决方案优与劣
480 93