MQTT协议:概念浸入

消息队列遥测传输(MQTT)协议已经使用了很多年,但是由于IoT的爆炸性增长,现在尤为重要:消费类设备和工业设备都实现了分布式网络和边缘计算,并且具有连续数据传输的设备已成为日常工作的一部分。生活。

这意味着随着时间的流逝,轻量级,开放且负担得起的协议将变得更加重要。 本文提供了对MQTT的概念性沉浸式介绍:它如何工作,现在如何使用以及将来如何使用。

小介绍


MQTT是基于发布者-订阅者的消息传递协议(pub / sub)。 IBM Andy Stanford-Clark和Cirrus Link的Arlene Nipper于1999年发布了初始版本。 他们将MQTT视为一种在带宽有限或通信无法预测的网络中维护机器之间通信的方法。 使用该管道的第一个选择是确保管道的各个部分彼此接触,并通过卫星与中央链接相接触。

在苛刻的操作条件下,该协议变得小巧轻便。 它是低功耗设备和电池寿命有限的理想选择。 这些现在包括无处不在的智能手机,以及不断增加的传感器和连接设备。

因此,MQTT已成为一种协议,用于在CPU功率和/或电池寿命有限的设备之间流传输数据,以及用于昂贵或低带宽,不可预测的稳定性或高延迟的网络。 这就是为什么MQTT被称为IoT的理想工具的原因。 它建立在TCP / IP协议的基础上,但是有一个MQTT-SN分支,可通过蓝牙,UDP,ZigBee和TCP / IP以外的其他物联网网络工作。

MQTT并不是同类中唯一的实时发布/子消息传递协议,但是它已经在依赖机器对机器通信的各种环境中得到了广泛的应用。 他的同are中包括Web应用程序消息协议流式文本消息协议替代消息队列协议

对于希望创建具有可靠功能和与连接到Internet的设备和应用程序(包括浏览器,智能手机和IoT设备)的应用程序广泛兼容的应用程序的开发人员,MQTT是合乎逻辑的选择。

MQTT的工作原理:基础


基于MQTT的通信系统由发布服务器,代理服务器和一个或多个客户端组成。 发布者不需要任何设置来接收消息的订阅者的数量或位置。 此外,订户不需要调谐到特定的发布者。 系统中可能有几个消息代理。



MQTT提供了一种创建通信通道层次结构的方法-一种带有叶子的分支。 每当发布者有新数据要分发给客户时,该消息就会附带一个交付控制说明。 较高级别的客户端可以接收每条消息,而较低级别的客户端可以接收仅与一个或两个基本通道(层次结构底部的“分支”)相关的消息。 这有利于信息交换,大小从2字节到256兆字节不等。

如何配置客户端以通过MQTT代理进行连接的示例:

var options = { keepalive: 60, username: 'FIRST_HALF_OF_API_KEY', password: 'SECOND_HALF_OF_API_KEY', port: 8883 }; var client = mqtt.connect('mqtts:mqtt.ably.io', options); 

MQTT代理发布或接收的任何数据都将以二进制格式编码,因为MQTT是二进制协议。 这意味着为了获取原始内容,您需要解释消息。 这是Ably和JavaScript的外观:

 var ably = new Ably.Realtime('REPLACE_WITH_YOUR_API_KEY'); var decoder = new TextDecoder(); var channel = ably.channels.get('input'); channel.subscribe(function(message) { var command = decoder.decode(message.data); }); 

MQTT代理有时可以累积与没有当前订户的频道有关的消息。 在这种情况下,将根据控制消息中的说明丢弃或保存消息。 这在新订户可能需要最近记录的数据点而不是等待下一个发送的情况下很有用。

值得注意的是,MQTT以明文形式传输安全凭证,否则不支持身份验证或安全功能。 这就是SSL框架发挥作用的地方 ,有助于保护传输的信息不被截取或篡改。

另外,在MQTT中,如果您根本不想将API密钥公开给实际的MQTT客户端,则可以对令牌使用Ably身份验证(对于没有SSL的MQTT,需要令牌来防止以明文形式传输API密钥)。 令牌认证示例:

 var options = { keepalive: 60, username: INSERT_TOKEN_HERE, password: '', port: 8883 }; var client = mqtt.connect('mqtts:mqtt.ably.io', options); client.subscribe("[mqtt]tokenevents", { /* Create a new token called 'NEW_TOKEN' */ client.end(); options.username = NEW_TOKEN; client = mqtt.connect('mqtts:mqtt.ably.io', options); }); 

MQTT功能:更加沉浸


根据IBM的说法 ,MQTT具有以下属性:

  • 与邮件内容无关
  • 分布式一对多通信和断开连接的应用程序的理想选择
  • 配有LWT功能(“遗嘱”,“遗嘱”),用于通知当事人与客户的异常断开连接
  • 依靠TCP / IP进行基本通信任务
  • 使用模板“最多一次”,“至少一次”和“恰好一次”来传递消息

MQTT系统的成员可以同时扮演发布者,使用者或两者的角色。

MQTT的显着特征之一是对通道的独特理解:每个通道都被视为文件路径,例如:

 channel = "user/path/channel" 

渠道确保每个客户都收到发给他的消息。 通过将通道视为文件路径,MQTT执行各种有用的通信功能,包括基于客户端订阅文件路径的位置(在哪个级别或在哪个分支)来过滤消息。

MQTT消息格式


查看构成每个MQTT消息的两个组件:

  • 字节1 :包含消息的类型(客户端的连接请求,订阅确认,Ping请求等),重复标记,保存消息的说明以及有关服务质量(QoS)的信息。
  • 字节2 :包含有关剩余消息长度的信息,包括有效负载和可选变量头中的任何数据。

字节1中的QoS标志值得特别注意,因为它是MQTT支持的可变功能的基础。 QoS标志根据消息的意图和紧急程度包含以下值:

  • 0 =不超过一次:服务器被触发并忘记。 邮件可能会丢失或重复。
  • 1 =至少一次:收件人确认交货。 消息可以重复,但可以保证传递
  • 2 =恰好一次:服务器提供交付。 邮件仅到达一次,不会丢失或重复

让我们看看如何在物联网设备和其他应用程序中使用不同的QoS级别。

在哪里可以使用MQTT?


随着物联网应用程序的大规模部署,MQTT以一种开放,简单且可扩展的方式脱颖而出,为消费和工业市场的广大用户群部署分布式计算和物联网功能。

如上所述,MQTT是为不受信任的网络和设备而构建的轻量级消息传递协议,受电源和CPU的限制。 但是,这并不意味着具有潜在数据包丢失的连接是其唯一的应用。 MQTT为各种类型的IoT基础设施提供各种服务级别,从重复数据采样到管理工业机器:

  • 环境传感器数据 :如上所述,MQTT支持“不止一次”消息传递模型。 在具有部分覆盖范围或高延迟的网络中,这意味着信息可能会丢失或重复 。 在远程传感器以指定的间隔记录和传输数据的区域,这不是问题,因为会定期接收新的读数。 远程环境中的传感器通常是低功耗设备,因此MQTT成为数据传输优先级相对较低的物联网传感器的理想解决方案。
  • 机器性能数据 :快速响应问题并防止停机。 例如,风力发电设施甚至需要在信息到达数据中心之前就保证向当地团队交付当前性能指标。 在这种情况下,消息的“至少一次”传递确保了必要的专家会及时通知适当的专家,即使他们是重复到达的。 这对于更高优先级的机器通信很重要。
  • 计费系统 :还有更多的优先级和准确的消息需要正确处理。 在不允许重复记录的业务情况下,包括在计费系统中, “恰好一次” QoS标志很有用。 这消除了计费或计费系统中包裹的重复或丢失,减少了商定的异常数量和不必要的矛盾。

什么时候不使用MQTT?


开发人员可以选择多种协议来设计和部署IoT双​​向通信通道,包括MQTT,HTTP, CoAPWebSocket (如果CPU /电池允许)以及其他协议。 MQTT是否为最佳选择取决于硬件和应用程序的任务。

MQTT协议专为具有极低带宽的环境而设计,在保存每个字节的过程中可能非常不灵活。 例如,规范仅定义了五个错误消息,服务器可以使用这些错误消息拒绝连接(例如,无效的用户名/密码或不可接受的协议版本)。 如果服务器要指向其他错误,则很不幸。 更糟糕的是,如果在启动连接后发生错误,则根本没有报告错误的机制。 服务器只能耸耸肩,突然终止TCP连接,从而使客户端不知道为什么会丢弃它(也没有任何办法将故意断开连接与临时网络问题区分开)。 对于习惯于更灵活,更容易调试(尽管在带宽方面较不经济)的发布/订阅协议的人们来说,这种Spartan方法似乎有些原始。

MQTT通常与HTTP一起使用,因此Google进行了一项研究,将它们在响应时间,流量和对开发人员重要的其他属性上进行了比较。 MQTT在Google测试中排名第一,但仅在可以重用连接以发送多个有效负载的条件下。

HTTP和MQTT是物联网应用程序的理想选择,因为其通信量相对较小,电池和内存需求较低。

CoAP是另一种经常与MQTT相比用于开发物联网系统的协议。 它们是相似的,但是有明显的区别。 MQTT是多对多协议,而CoAP基本上是用于服务器和客户端之间通信的一对一协议。 同时,CoAP提供了MQTT不具备的元数据,发现和内容协商功能。

如果客户端仅应接收数据,则“ 服务器发送事件”也是一个合适的选择。

如何快速设置MQTT


GitHub上的MQTT存储库包含各种语言的开源MQTT库的广泛列表 。 以下是使用开源MQTT代理,JavaScript库和.NET库进行自定义的两个示例。

Eclipse Mosquitto-开源MQTT代理


Eclipse Mosquitto是一个开源消息代理(EPL / EDL),实现了MQTT协议版本5.0、3.1.1和3.1。 Mosquitto轻巧,适合在所有设备上使用:从低功率单板计算机到功能强大的服务器。

MQTT.js


MQTT.js是MQTT协议的客户端库,用JavaScript编写,用于Node.js和浏览器。 这是使用MQTT.js发送消息的示例:

 var mqtt = require('mqtt') var client = mqtt.connect('mqtt://test.mosquitto.org') client.on('connect', function () { client.subscribe('presence', function (err) { if (!err) { client.publish('presence', 'Hello mqtt') } }) }) client.on('message', function (topic, message) { // message is Buffer console.log(message.toString()) client.end() }) 

MQTTnet


MQTTnet是一个高性能.NET库,它提供客户端和MQTT服务器(代理)。

MQTT客户端安装:

 // Create a new MQTT client. var factory = new MqttFactory(); var mqttClient = factory.CreateMqttClient(); 

配置MQTT客户端设置后,可以建立连接。 以下代码显示了如何连接到服务器:

 // Use WebSocket connection. var options = new MqttClientOptionsBuilder() .WithWebSocketServer("broker.hivemq.com:8000/mqtt") .Build(); await client.ConnectAsync(options); 

接收传入消息:

 client.UseApplicationMessageReceivedHandler(e => { Console.WriteLine("### RECEIVED APPLICATION MESSAGE ###"); Console.WriteLine($"+ Topic = {e.ApplicationMessage.Topic}"); Console.WriteLine($"+ Payload = {Encoding.UTF8.GetString(e.ApplicationMessage.Payload)}"); Console.WriteLine($"+ QoS = {e.ApplicationMessage.QualityOfServiceLevel}"); Console.WriteLine($"+ Retain = {e.ApplicationMessage.Retain}"); Console.WriteLine(); Task.Run(() => client.PublishAsync("hello/world")); }); 

出版后:

 var message = new MqttApplicationMessageBuilder() .WithTopic("MyTopic") .WithPayload("Hello World") .WithExactlyOnceQoS() .WithRetainFlag() .Build(); await client.PublishAsync(message); 

有关更多示例,请参见MQTTnet文档和Wiki

企业级提供商拥有现成的MQTT服务器,用于在移动应用程序,工业机器和其他各种IoT用途之间进行可伸缩的消息传递。 本指南告诉您如何通过企业级代理使用MQTT。

那么缩放呢?


在扩展MQTT时,有两个注意事项:1)这是正确的协议吗? 2)不管协议选择如何,都需要什么基础架构和网络功能来处理使用MQTT的设备之间增加的流量。

轻量级机器对机器(LWM2M)是可以在企业级与MQTT一起使用的另一种协议。 与MQTT相比,它有时更适合于长期物联网系统 。 MQTT非常适合毫不费力地进行IoT的试运行,而LWM2M为长期的通用基础架构提供了功能。 LWM2M还提供了出色的设备管理工具,例如连接监视,固件更新和远程设备操作。 对于拥有大量不受管理的设备并将大量数据发送到中央平台的企业,LWM2M是最佳选择。 尽管如此,我们谈论的是物联网的大规模部署,因此通常MQTT不仅仅是一个适当的选择。 另外,MQTT更常见并且具有更广泛的支持。

现在介绍基础设施的可能性。 当涉及服务器加载时,同时连接的数量很少成为瓶颈。 大多数优秀的MQTT服务器/代理都支持数千个并发连接,但是在MQTT服务器接收到实际数据之后,处理和回复消息所需的工作量是多少? 通常,存在各种潜在问题,例如与数据库之间的读取和写入,与服务器的集成,每个客户端的资源分配和管理等。一旦一台计算机停止处理负载,您就需要添加其他服务器,也就是说,请考虑负载平衡,连接到不同服务器的客户端之间的消息同步,对客户端状态的通用访问,而不考虑连接时间或客户端所连接的特定服务器-产品列表 zhaetsya并继续。

这些问题应另作文章,并且可以在我们博客的“工程”部分找到很多信息。 特别是,请参阅有关为大型实时消息传递基础结构提供服务的一些复杂性的文章。

MQTT的当前情况如何?


在2019年4月,OASIS发布了MQTT v5.0作为官方标准。 OASIS是由600个成员组织和5,000个个人成员组成的非营利性联盟。

5.0版引入了许多实时系统开发人员应该感兴趣的新功能 。 这些新功能与MQTT的当前版本向后兼容。 其中包括:

  • 改进的错误报告 :现在,返回码可以通知由于某种原因未在传输数据。 支持可选字符串以指示原因。 它们有助于改善故障排除诊断。
  • 共享订阅 :为了帮助平衡负载,可以在接收方的多个客户端之间共享订阅。
  • 邮件属性 :5.0版将元数据作为邮件头的一部分引入。 它可以向最终用户传达其他信息,或促进以下列出的其他一些功能。
  • 通道别名 :发布者可以用数字标识符替换通道,以减少要传输的字节数。
  • 邮件到期日期:如果系统在指定的时间内无法传递邮件,则可以将邮件标记为自动删除。

有关MQTT 5.0新功能的完整列表,请参见官方标准的附录C。

除了市场上的许多消费类设备和服务外,MQTT还用于各种形状和规模的公司基础架构中。 这些是智能手机和平板电脑,能源监控系统,医疗设备,石油钻机和钻机,汽车和航空航天工业,以及用于物料处理,建筑,供应链,零售等的传感器和机器视觉系统。

MQTT和Ably


MQTT是流行的,广泛支持的且相对成熟的协议。 它对许多实时应用程序非常有用,而不仅仅是部署物联网。 但是,随着实时数据的生产和使用量呈指数级增长 ,MQTT可能并不总是满足您流需求的正确协议。 请关注我们的实时概念部分,以获取有关其他协议以及它们如何适合您的情况的信息。

Ably提供了代理和MQTT协议适配器 ,可以双向转换为Ably自己的协议,从而使您可以与任何现有系统和连接集成。 支持的WebSocket,HTTP,SSE,gRPC(正在开发中),STOMP,AMQP和其他协议,用于实时组织分布式消息传递基础结构。 有40多个SDK客户端库,并支持专有的实时协议。

Source: https://habr.com/ru/post/zh-CN463669/


All Articles