网络上搜索MQTT协议,会出现太多的解释,这里就不做官方标准释义的复制了。这一节我们从实战理解角度,通俗的将MQTT协议的作用及实现原理说一下,旨在可以快速理解MQTT协议。所以可能会出现很多看似不标准的解释,但是更容易理解MQTT的内涵,对MQTT十分精通者请忽略此文。

  在物联网项目中,经常出现的要求是“有限环境”。什么意思呢,通俗说就是网络可能不太稳定,带宽也可能很小,网速也比较低,硬件MCU性能也很低,要求在这种情况下也能可靠联网传输信息。看到这里大家就会想到我前面提到的短指令中说到的问题了,不是我们认为开发容易好维护就可以的,首先要满足工作环境的需要,项目才可以成功落地,否则都是无用功。

  在N年前最初尝试做物联网项目的时候,很多用HTTP协议做硬件设备信息的上报,利用返回结果控制硬件设备执行的项目(其实现在也有人还在使用)。这样硬件设备信息上报的即时性没有问题,但经过服务端发送控制指令去操控硬件设备的时候,及时性就很难满足。因为HTTP是单方向主动请求服务器,有请求才有返回,返回后就断开了。要想服务端与硬件设备再有联系,只能等硬件设备通过HTTP的下一个请求上来才可以,也就是服务端不能主动推送消息给硬件设备。看到这里可能会有很多人会说出N多种基于HTTP服务端推送的方案,但是很抱歉,在物联网环境中都不适合。因为无论是轮询还是长连接,用HTTP维持所消耗的网络资源和硬件性能要求对项目来说都是高昂的,必须考虑项目落地要求的“有限环境”。对于网络不稳定和带宽低(比如移动网络、信号弱的区域等)的环境,极大可能造成项目运行失败,这是不能接受的结果。

  那么为什么推荐MQTT协议呢?因为MQTT协议具备以下几点特征:
  1、网络开销小,消息头最小只有2字节,这相比HTTP大大降低了网络流量。
  2、是可保持的会话,为实现服务端及时推消息提供了条件。
  3、是异步消息机制,不会阻塞占用资源。
  4、具备异常中断通知机制,可以获得硬件在线信息变化,及时得到掉线消息。
  5、使用发布/订阅消息模式,一对多或多对一的消息传输,实现与应用程序的解耦。
  6、传输可靠性可控,及三种服务质量,分别是至多一次、至少一次、只有一次。指的是发布者发出的信息,代理服务和订阅者是否收到的情况。
  7、客户端程序够轻量,可在很多嵌入式设备中运行。
  8、可满足低带宽、高延迟、不稳定的网络环境。

  MQTT协议中,需要两个端,分别是服务端和客户端;有三个身份,分别是发布者(Publish),代理(Broker)、订阅者(Subscribe)。
  在MQTT协议中,客户端不能直接对客户端实行端到端的收发消息,必须经过服务端管理分配,所以服务端要运行一个代理服务,也就是三个身份之一的代理身份。消息的发送方称为发布者,该消息的需要接收者称之为订阅者。发布者把消息发送给代理,代理负责检查都谁需要接收这个消息(这个就是订阅),需要的就转发给它。因为要识别不同的消息,所以MQTT协议制定了主题标准,也就是给消息加上了标签。发布者发送的消息总是要带上标签的,代理根据谁订阅了这个标签来决定转发给谁,这个标签就称之为主题(Topic),标签携带我们需要传输的信息内容称之为负载(Payload)。

  为了实现异常中断通知机制,所以在客户端与服务端首次连接的时候,就要携带一条相对特殊的主题,主题内容是如果自己掉线了,希望告知需要知道自己掉线一方一些信息,这就是遗嘱消息(Will Message)。这个主题自己在线时,代理不会做任何转发,当自己掉线达到一定时间(即心跳间隔Keep Alive timer),代理会检查谁订阅了这个主题,就转发给谁(当然可以多人订阅),这就实现了异常中断(掉线)通知。

  下面继续深入理解一下MQTT协议的工作过程。

  发布者、订阅者、代理与主题发布与订阅间的关系:

  通过上图,我们可以看出,同一个客户端既可以是发布者,也可以是订阅者。一个主题只有一个发布者,但是可以有很多个订阅者。一个客户端也可以订阅多个主题。

  客户端连接到代理:

  工作的第一步是建立连接,MQTT协议也是建立在TCP/IP基础上的通信协议,首先要在客户端与代理服务端建立一个TCP连接。建立连接的过程是由客户端主动发起的,代理服务一直是处于指定端口的监听状态,当监听到有客户端要接入的时候,就会立刻去处理。客户端在发起连接请求时,携带客户端ID、账号、密码(无账号密码使用除外,正式项目不会允许这样)、心跳间隔时间等数据。代理服务收到后检查自己的连接权限配置中是否允许该账号密码连接,如果允许则建立会话标识并保存,绑定客户端ID与会话,并记录心跳间隔时间(判断是否掉线和启动遗嘱时用)和遗嘱消息等,然后回发连接成功确认消息给客户端,客户端收到连接成功的确认消息后,进入下一步(通常是开始订阅主题,如果不需要订阅则跳过)。上图只做了连接成功的示意图,连接失败和拒绝先脑补一下即可,后面会设计到更具体的。

  客户端订阅主题:

  客户端将需要订阅的主题经过SUBSCRIBE报文发送给代理服务,代理服务则将这个主题记录到该客户端ID下(以后有这个主题发布就会发送给该客户端),然后回复确认消息SUBACK报文,客户端接到SUBACK报文后知道已经订阅成功,则处于等待监听代理服务推送的消息,也可以继续订阅其他主题或发布主题。

  客户端发布主题:

  当某一客户端发布一个主题到代理服务后,代理服务先回复该客户端收到主题的确认消息,该客户端收到确认后就可以继续自己的逻辑了。但这时主题消息还没有发给订阅了这个主题的客户端,代理要根据质量级别(QoS)来决定怎样处理这个主题。所以这里充分体现了是MQTT协议是异步通信模式,不是立即端到端反应的。

  如果发布和订阅时的质量级别QoS都是至多一次,那代理服务则检查当前订阅这个主题的客户端是否在线,在线则转发一次,收到与否不再做任何处理。这种质量对系统压力最小。
  如果发布和订阅时的质量级别QoS都是至少一次,那要保证代理服务和订阅的客户端都有成功收到才可以,否则会尝试补充发送(具体机制后面讨论)。这也可能会出现同一主题多次重复发送的情况。这种质量对系统压力较大。
  如果发布和订阅时的质量级别QoS都是只有一次,那要保证代理服务和订阅的客户端都有成功收到,并只收到一次不会重复发送(具体机制后面讨论)。这种质量对系统压力最大。

  代理最终将主题消息转发给订阅者,至少是做了转发操作,成功与否决定质量等级。更详细的消息质量等级控制后面会有专门详细叙述。

  关于MQTT协议的实现原理通俗解释就到这里,希望能让刚刚接触MQTT的开发者有个整体流程的印象和理解,后面会详细讨论MQTT协议的定义、配置等。

  本节完,待续......

转战物联网·基础篇05-通俗理解MQTT协议的实现原理和异步方式的更多相关文章

  1. 转战物联网·基础篇07-深入理解MQTT协议之控制报文(数据包)格式

      在MQTT协议中,一个控制报文(数据包)的结构按照前后顺序分如下三部分: 结构名 中文名 解释说明 Fixed header 固定报头 报文的最开始部分,所有报文都包含这个部分 Variable ...

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

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

  3. 转战物联网·基础篇08-例说MQTT协议各控制报文

      前面讨论了MQTT协议的控制报文的格式,下面分别举例探讨各个控制报文的详细内容. 01.CONNECT – 连接服务端   客户端到服务端的网络连接建立后,客户端发送给服务端的第一个报文必须是CO ...

  4. 转战物联网·基础篇09-选择MQTT协议还是CoAP协议

      前面章节介绍过,MQTT协议和CoAP协议都是物联网中比较流行的协议,都对传输量做了很大的精简,传输开销小,以适应物理网的网络环境.   XMPP协议也有人说是适合物联网通信的,但它是基于XML, ...

  5. 转战物联网·基础篇03-从JSON数据到短指令谈思维的转变

      了解了物联网项目的大体结构之后,我们先从物联网的联网相关部分说起,这也是物联网项目中的关键环节.在联网环节中,不仅要考虑如何连接上,还要考虑连接后如何传输数据.换句话说数据是以什么格式进行传输,对 ...

  6. iOS系列 基础篇 05 视图鼻祖 - UIView

    iOS系列 基础篇 05 视图鼻祖 - UIView 目录: UIView“家族” 应用界面的构建层次 视图分类 最后 在Cocoa和Cocoa Touch框架中,“根”类时NSObject类.同样, ...

  7. 物联网防火墙himqtt源码之MQTT协议分析

    物联网防火墙himqtt源码之MQTT协议分析 himqtt是首款完整源码的高性能MQTT物联网防火墙 - MQTT Application FireWall,C语言编写,采用epoll模式支持数十万 ...

  8. Java多线程系列--“基础篇”05之 线程等待与唤醒

    概要 本章,会对线程等待/唤醒方法进行介绍.涉及到的内容包括:1. wait(), notify(), notifyAll()等方法介绍2. wait()和notify()3. wait(long t ...

  9. 【物联网云端对接-3】通过MQTT协议与微软Azure IoT Hub进行云端通信

    在上一篇文章<通过MQTT协议与阿里云物联网套件进行云端通信>中,我们介绍了通过MQTT对接阿里云的物联网套件.其实同样的代码,稍加调整也可以对接到微软Azure IoT hub上,不过需 ...

随机推荐

  1. C++之下载Visual Studio Installer缓慢问题

    将IPv4中设置DNS首选项为8.8.8.8即可.

  2. react中使用prop-types检测props数据类型

    一.为什么使用prop-types 在多人开发时,当被人使用自己定义的组件时,有可能出现类型传错的情况,而在自己的组件上加上prop-types,他可以对父组件传来的props进行检查,加入父组件中想 ...

  3. 基于V6的中移动物联测试例子,当前测试还挺稳定

    下载: 链接:https://pan.baidu.com/s/1Gz8mEffDGXNSK8lIsAIUEg   提取码:2sur 测试步骤看此贴,跟V7开发板是一样的: 基于H7的中移动物联例子以及 ...

  4. C语言程序设计100例之(25):确定进制

    例25    确定进制 问题描述 6*9 = 42 对于十进制来说是错误的,但是对于13进制来说是正确的.即 6(13)* 9(13)= 42(13),因为,在十三进制中,42 = 4 * 13 + ...

  5. 2019 Vue开发指南:你都需要学点啥?

    转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者.原文出处:https://dzone.com/articles/vue-development-in-2019 ...

  6. java使用htmlunit工具抓取js中加载的数据

    htmlunit 是一款开源的java 页面分析工具,读取页面后,可以有效的使用htmlunit分析页面上的内容.项目可以模拟浏览器运行,被誉为java浏览器的开源实现.这个没有界面的浏览器,运行速度 ...

  7. 一些webpack常见编译报错的解决方案

    重新安装依赖可以解决80%的webpack编译报错问题. rm -rf node_modules rm package-lock.json npm cache clear --force npm in ...

  8. getattribute方法,Python属性访问拦截器的用法

    __getattribute__()方法是属性访问时的拦截器,每当访问属性的时候,会先执行这个方法,然后再执行访问属性的操作步骤,可以用来记录属性访问的log.代码示例如下:   class Itca ...

  9. 12-《Node.js开发指南》-核心模块

    全局对象 Node.js中的全局对象是global 所有全局变量(除了global本身以外)都是global对象的属性 最根本的作用为全局变量的宿主 全局变量 //满足以下条件的是全局变量 a.在最外 ...

  10. SpringBoot:@Scope注解学习

    概述 先通过注解的javadoc,可以了解到,@Scope在和@Component注解一起修饰在类上,作为类级别注解时,@Scope表示该类实例的范围,在和@Bean一起修饰在方法上,作为方法级别注解 ...