在机智云的整个架构里面,如上图,GAgent实现了从模块到云端的数据交互,其实GAgent里面就是用MQTT协议实现的,可见MQTT协议的重要性。今天介绍MQTT的发布、订阅和取消订阅。 回顾
在上一篇**中,我们解释了发布/订阅模式是如何工作的以及如何在MQTT中应用,以下我们把要点回顾下:发布或者订阅解耦一个客户端,就是从另一个客户端(或更多客户端)发送特定消息(称为发布者),为了确定哪个消息发送到哪个客户端,MQTT使用了主题。主题是层次结构的字符串,用于消息过滤和路由。
在上一章节的最后我又更具理论性的分析了,发布/订阅是什么,以及如何从消息排队方法中区分MQTT。这篇**干货将更多,主要介绍MQTT的基本知识。这一章,我们讨论的主题是MQTT客户端和代理服务器的定义以及MQTT连接的基础知识,如何连接、连接需要的参数。 引言
我们已经看看完了MQTT的发布和订阅后,所有的设备都要和代理服务器连接的,我们在讲连接之前应该理解下客户端和代理服务器。 客户端
在**中,我们讨论的客户端都是MQTT客户端,说的发布者和订阅者也都指的是MQTT客户端的发布和订阅(通常,MQTT客户端可以同时发布和订阅)MQTT客户端是从微控制器到完整的服务器的任何设备,它具有运行的MQTT库,并通过任何类型的网络连接到MQTT代理。这是一个非常小且资源有限的设备它通过无线网络连接,并且设定一定参数,或者运行图形化MQTT客户端的典型计算机用于测试目的,总的来说基本上是具有TCP / IP协议栈并在其上支持MQTT协议的任何设备。
MQTT协议的客户端实现非常直观,简单,有人会问了,为什么MQTT非常适合小型设备呢?MQTT客户端库可用于各种各样的编程语言,如Android, Arduino, C, C++, C#, Go, iOS, Java, JavaScript, .NET. 可以在维基百科上找到MQTT的完整的列表。 代理
MQTT客户端的对应方就是MQTT代理服务器,这是任何发布和订阅协议的核心,根据具体实现情况,代理可以处理多达数千个并发连接的MQTT客户端。代理主要负责接收所有消息,过滤它们,决定谁对其感兴趣,然后将消息发送给相应订阅客户端。它还拥有所有持久客户端的会话,包括订阅和错过的消息。
代理的另一责任是给客户端认证和授权,而且在大多数时候,代理也是可扩展的,这样可以轻松地自定义身份验证,授权并且集成到后端系统中。集成是一个重要的方面,因为代理通常是直接暴露在互联网上并处理大量客户端的组件,然后将消息传递到下游分析和处理系统。
正如我们在我们早期博客中所描述的一样,订阅所有消息并不是一个真正的选择,所有的代理都是中心枢纽,每个消息都需要通过它的。因此,重要的是,它具有高度可扩展性,可集成到后端系统中,这样易于监控,当然也具有抗故障性,才能保障稳定。例如,HiveMQ通过使用最先进的事件驱动网络处理,一个开放的插件系统和标准的监控为用户提供服务。 MQTT连接
MQTT协议基于TCP / IP的,客户端和代理都需要具有TCP / IP协议栈。
MQTT连接本身始终在一个客户端和代理之间,没有客户端直接连接到另一个客户端。通过客户端向代理发送CONNECT消息来启动连接。具有CONNACK的代理响应并发送状态代码。建立连接后,只要客户端没有发送断开连接命令或者断开连接网络,代理将一直保持打开状态。
MQTT客户端一般是连接路由器设备的,它们正在使用网络地址转换(NAT),以便从专用网络地址(如192.168.x.x,10.0.x.x)转换为面向公众的公共网络。如前所述,MQTT客户端第一步就要要发送CONNECT消息。因此,NAT后面的客户端没有任何问题,因为代理具有公共地址,并且连接将保持打开,以允许在初始CONNECT之后双向发送和接收消息。
下面让我们看看MQTT客户端发送的连接信息。前面已经提到,这是从客户端到代理发起连接。如果CONNECT消息格式错误(根据MQTT规范)或打开网路超时,代理将关闭连接。这是合理的行为,这样可以避免恶意客户端攻击,减慢代理的速度。 一个完好的客户端将发送一个包含以下内容的连接消息:
此外,CONNECT消息中还包含其他信息,这对MQTT库的编写者而言比对库的使用者更加关心。如果您对详细信息有兴趣,请查看MQTT 3.1.1规范。 下面让我们逐个浏览所有这些项目参数吧: 客户端标识符(简称ClientId)是连接到MQTT代理的每个MQTT客户端的标识符。正如标识符的含义那样,每个代理应该是唯一的。代理使用它来识别客户端和客户端的当前状态。如果不需要一个状态来保持代理,在MQTT 3.1.1(当前标准)中,也可以发送一个空的ClientId。这导致没有任何状态的连接,条件是 Clean Session是真的,否则连接将被拒绝。 Clean Session标志指示代理,客户端是否要建立持久会话。持久会话(CleanSession为假)表示代理将存储客户端的所有订阅以及所有错过的信息。当使用服务质量(QoS)1或2进行订阅时。如果Clean Session设置为真,则代理不会为客户端存储任何东西,并且还将清除以前持续会话中的所有信息。 MQTT允许发送用于验证客户端的用户名和密码以及授权。然而,密码是以明文形式发送的,如果它没有通过实现加密或散列,或者使用TLS。我们强烈建议使用用户名和密码以及安全的传输,在像HiveMQ这样的代理中,也可以使用SSL证书对客户端进行身份验证,因此不需要用户名和密码。 Will Message是MQTT的最后一个意愿和遗嘱特征的一部分。它允许通知其他客户端,当客户端不正常地断开连接。连接客户端将在CONNECT消息中以MQTT消息和主题的形式提供他的意愿。如果客户端不正常地断开连接,代理客户端会发送此消息。我们会在后面的**中单独介绍一下。 KeepAlive是一个时间间隔,客户端通过向代理发送常规PING请求消息。代理将与PING响应,这种机制将确定双方是否仍然存在和正常通信。这个我们将在以后的一篇**中详细介绍一下。这基本上都是从MQTT客户端连接到MQTT代理所需的所有信息。每个MQTT库通常都会有其他选项,可以进行具体配置。 当代理获得CONNECT消息时,代理有义务使用CONNACK消息进行响应。CONNACK只包含两个数据条目:会话存在标志,连接确认标志。 会话存在标志指示,代理是否已经具有来自先前交互的客户端的持久会话。如果客户端连接并将CleanSession设置为真,则此标志始终为假,因为没有会话可用。如果客户端将CleanSession设置为假,则该标志取决于该ClientId是否存在可用于的会话信息。如果存储会话信息,则该标志为真,否则为假。该标志在MQTT 3.1.1中新添加,并帮助客户端确定是否必须订阅主题,或者是否仍然存储在他的会话中。 CONNACK中的第二个标志是连接确认标志。它指示客户端,是否连接成功和没有连接成功的原因是什么。
在下表中,您可以一目了然地看到所有的返回代码。
这些更详细的说明可以在MQTT规范中找到 问题
您可能会问,即使没有发送消息,MQTT如何保持连接的打开状态?或者如何知道连接何时丢失?你必须耐心等待,但是我们将在后面的整个博客里面写下一些关于这个主题的必要内容。
这就是我们的MQTT 要点系列的第三部分的结尾。我们希望您能了解至少一件关于MQTT的基本知识,并期待下一篇关于如何在MQTT中发布,订阅和取消订阅的**。 学习总结
都是很重点的内容,可以先看看这个文档再去看官方协议,毕竟这个要比官方协议讲的要通俗易懂些,很有收获的。
|