MQTT 协议快速入门

课程亮点

  • MQTT 协议实例全解析
  • MQTT 协议的最佳实践和反模式
  • MQTT 协议的安全性实践
  • AI+IoT 项目实战

本课程深入浅出地介绍了 MQTT 协议的各种特性,对每个协议特性都辅以具体代码进行讲解,并通过一个 IoT+AI 项目实战来具体展现 MQTT 在移动端、Web 端的使用,MQTT Broker 的架设等场景。

作者介绍

付强,十余年从业经验,从 C 语言到 Web 开发,从微服务架构到移动端开发,涉猎范围很广。曾就职于趋势科技、诺基亚,在德国和硅谷的 Startups 工作过,现在从事物联网方向的创业。

课程大纲

MQTT 协议快速入门_第1张图片

适宜人群

  • 对物联网平台入门感兴趣的开发人员
  • 有一定经验的 IM 平台、移动推送平台开发人员
  • 渴望学习更多物联网实际开发经验的人员

课程内容

开篇词:MQTT 协议简介

为什么要学 MQTT

物联网曾被认为是继计算机、互联网之后,信息技术行业的第三次浪潮。随着基础通讯设施的不断完善,尤其是 5G 的出现,进一步降低了万物互联的门槛和成本。物联网本身也是 AI 和区块链应用很好的落地场景之一,各大云服务商也在纷纷上架物联网平台和服务。在 AI 和区块链的热潮过去之后,物联网很有可能成为下一个风口,在风口到来之前,提前进行一些知识储备,是很有必要的。

物联网通讯是物联网的一个核心内容,目前物联网的通讯协议并没有一个统一的标准,比较常见的有 MQTT、CoAP、DDS、XMPP 等,在这其中,MQTT(消息队列遥测传输协议)应该是应用最广泛的标准之一。我们可以来看一下各大云服务商提供的物联网套件服务:

阿里云

MQTT 协议快速入门_第2张图片

腾讯云

MQTT 协议快速入门_第3张图片

青云

MQTT 协议快速入门_第4张图片

所以入门物联网,掌握 MQTT 是一个非常必要的步骤。

MQTT 是什么

MQTT 的全称为 Message Queue Telemetry Transport,是在 1999 年,由 IBM 的 Andy Stanford-Clark 和 Arcom 的 Arlen Nipper 为了一个通过卫星网络连接输油管道的项目开发的。为了满足低电量消耗和低网络带宽的需求,MQTT 协议在设计之初就包含了以下一些特点:

  1. 实现简单
  2. 提供数据传输的 QoS
  3. 轻量、占用带宽低
  4. 可传输任意类型的数据
  5. 可保持的会话(session)

之后 IBM 一直将 MQTT 作为一个内部协议在其产品中使用,直到 2010 年,IBM 公开发布了 MQTT 3.1 版本。在 2014 年,MQTT 协议正式成为了 OASIS(结构化信息标准促进组织)的标准协议。随着多年的发展,MQTT 协议的重点也不再只是嵌入式系统,而是更广泛的物联网(Internet of Things)世界了。

MQTT 协议是什么?简单地来说 MQTT 协议有以下特性:

  • 基于 TCP 协议的应用层协议;
  • 采用 C/S 架构;
  • 使用订阅/发布模式,将消息的发送方和接受方解耦;
  • 提供 3 种消息的 QoS(Quality of Service): 至多一次,最少一次,只有一次;
  • 收发消息都是异步的,发送方不需要等待接收方应答。

虽然 MQTT 协议名称有 Message Queue 两个词,但是它并不是一个像 RabbitMQ 那样的一个消息队列,这是初学者最容易搞混的一个问题。MQTT 跟传统的消息队列相比,有以下一些区别:

  1. 在传统消息队列中,在发送消息之前,必须先创建相应的队列;在 MQTT 中,不需要预先创建要发布的主题(可订阅的 Topic);
  2. 在传统消息队列中,未被消费的消息总是会被保存在某个队列中,直到有一个消费者将其消费;在 MQTT 中,如果发布一个没有被任何客户端订阅的消息,这个消息将被直接扔掉;
  3. 在传统消息队列中,一个消息只能被一个客户端获取,在 MQTT 中,一个消息可以被多个订阅者获取,MQTT 协议也不支持指定消息被单一的客户端获取。

MQTT 协议可以为大量的低功率、工作网络环境不可靠的物联网设备提供通讯保障。而它的应用范围也不仅如此,在移动互联网领域也大有作为:很多 Android App 的推送功能,都是基于 MQTT 实现的,也有一些 IM 的实现,是基于 MQTT 的。

怎么学习 MQTT

在本课程中,我们将逐一学习 MQTT 协议的每一个特性以及其最佳实践,并辅以实际的代码来进行讲解。

在学习完 MQTT 协议的所有特性以后,我们将做一个 IoT+AI 实战——将《物体识别:TensorFlow on Android》一课中的 App 改造成可以实时发布识别结果。在这个过程中,读者将学习:

  • MQTT 数据包、数据收发流程详细解析
  • 如何在 Web 端和移动端正确地使用 MQTT
  • 如何搭建自己的 MQTT Broker
  • 如何增强 MQTT 平台的安全性
  • 使用 MQTT 设计和开发 IoT 产品和平台的最佳实践
  • MQTT 5.0 的新特性

在学习完本课程以后,读者将具备独立架设和开发基于 MQTT 协议的 IoT 平台、实时通信系统,及相关物联网产品的能力;同时也可以将本课程当做 MQTT 协议的参考文档,对协议内容有疑问的时候可随时查询。

课程中使用的 MQTT 协议版本为 3.1.1,代码主要使用 MQTT 的 Node.js 实现来进行演示。

点击了解更多《MQTT 协议快速入门》

第01课:MQTT 的基础概念

在这一课中,让我们来学习 MQTT 协议的基本概念和术语,同时也会介绍一下本课程中代码的开发环境搭建。本节课核心内容包括:

  • MQTT 协议的通信模型
  • MQTT Client
  • MQTT Broker
  • MQTT 协议数据包

1.1 MQTT 协议的通信模型

就像我们在之前提到的,MQTT 的通信是通过发布/订阅的方式来实现的,消息的发布方和订阅方通过这种方式来进行解耦,它们没有直接地连接,它们需要一个中间方。在 MQTT 里面我们称之为 Broker,用来进行消息的存储和转发。一次典型的 MQTT 消息通信流程如下所示:

MQTT 协议快速入门_第5张图片

  1. 发布方将消息发送到 Broker;
  2. Broker 接收到消息以后,检查下都有哪些订阅方订阅了此类消息,然后将消息发送到这些订阅方;
  3. 订阅方从 Broker 获取该消息。

在之后的课程里面,我们将发送方称为 Publisher,将订阅方称为 Subscriber。

1.2 MQTT Client

任何终端,嵌入式设备也好,服务器也好,只要运行了 MQTT 的库或者代码,我们都称为 MQTT 的 Client。Publisher 和 Subscriber 都属于 Client,Pushlisher 或者 Subscriber 只取决于该 Client 当前的状态——是在发布还是在订阅消息。当然,一个 Client 可以同时是 Publisher 和 Subscriber。

MQTT Client 库在很多语言中都有实现,包括 Android、Arduino、Ruby、C、C++、C#、Go、iOS、Java、JavaScript,以及 .NET 等。如果你要查看相应语言的库实现,可以在这里找到。

本课程中,我们主要使用 Node.js 的 MQTT Client 库来进行演示,所以需要先安装 Node.js,然后安装 MQTT Client 的 Node.js 包:

npm install mqtt -g

1.3 MQTT Broker

如前面所讲的,Broker 负责接收 Publisher 的消息,并发送给相应的 Subscriber,它是整个 MQTT 订阅/发布的核心。在实际应用中,一个 MQTT Broker 还应该提供以下一些功能:

  • 可以横向扩展,比如集群,来满足大量的 Client 接入;
  • 可以扩展接入业务系统;
  • 易于监控,满足高可用性。

我们在导读里面提到的阿里云、腾讯云、青云之类的云服务商提供的 MQTT 服务,其实就可以理解为他们提供了满足上述要求的 MQTT Broker。

在本课程中,我们使用一个公共的 MQTT Broker —— iot.eclipse.org 做演示,同时也会学习如何搭建一个 MQTT Broker。

1.4 MQTT 协议数据包

MQTT 协议的数据包格式非常简单,一个 MQTT 协议数据包由下面三个部分组成:

  • 固定头(Fixed header):存在于所有的 MQTT 数据包中,用于表示数据包类型及对应标识,表明数据包大小;
  • 可变头(Variable header):存在于部分类型的 MQTT 数据包中,具体内容由相应类型的数据包决定;
  • 消息体(Payload):存在于部分 MQTT 数据包中,存储消息的具体数据。

接下来看一下固定头的格式,可变头和消息体我们将在讲解各种具体类型的 MQTT 协议数据包的时候 case by case 地讨论。

固定头格式:

Bit 7 6 5 4 3 2 1 0
字节 1 MQTT 数据包类型 MQTT 数据包 Flag, 内容由数据包类型指定
字节 2…… 数据包剩余长度

固定头的第一个字节的高 4 位 bit 用于指定该数据包的类型,MQTT 的数据包有以下一些类型:

名称 方向 描述
Reserved 0 不可用 保留位
CONNECT 1 Client 到 Broker Client 请求连接到 Broker
CONNACK 2 Broker 到 Client 连接确认
PUBLISH 3 双向 发布消息
PUBACK 4 双向 发布确认
PUBREC 5 双向 发布收到
PUBREL 6 双向 发布释放
PUBCOMP 7 双向 发布完成
SUBSCRIBE 8 Client 到 Broker Client 请求订阅
SUBACK 9 Broker 到 Client 订阅确认
UNSUBSCRIBE 10 Client 到 Broker Client 请求取消订阅
UNSUBACK 11 Broker 到 Client 取消订阅确认
PINGREQ 12 Client 到 Broker PING 请求
PINGRESP 13 Broker 到 Client PING 应答
DISCONNECT 14 Client 到 Broker Client 主动中断连接
Reserved 15 不可用 保留位

固定头的低 4 位 bit 用于指定数据包的 Flag,不同的数据包类型,其 Flag 的定义是不一样的,每种数据包对应的 Flag 如下:

数据包 标识位 Bit 3 Bit 2 Bit 1 Bit 0
CONNECT 保留位 0 0 0 0
CONNACK 保留位 0 0 0 0
PUBLISH MQTT 3.1.1 使用 DUP QoS QoS RETAIN
PUBACK 保留位 0 0 0 0
PUBREC 保留位 0 0 0 0
PUBREL 保留位 0 0 0 0
PUBCOMP 保留位 0 0 0 0
SUBSCRIBE 保留位 0 0 0 0
SUBACK 保留位 0 0 0 0
UNSUBSCRIBE 保留位 0 0 0 0
UNSUBACK 保留位 0 0 0 0
PINGREQ 保留位 0 0 0 0
PINGRESP 保留位 0 0 0 0
DISCONNECT 保留位 0 0 0 0

注意:DUP、QOS、RETAIN 标识的使用将在后续的课程中详细讲解。

从固定头的第 2 字节开始是用于标识 MQTT 数据包长度的字段,最少一个字节,最大四个字节,每一个字节的低 7 位用于标识值,范围为 0~127。最高位的 1 位是标识位,用来说明是否有后续字节来标识长度。例如:标识为 0,代表为没有后续字节;标识为 1,代表后续还有一个字节用于标识包长度。MQTT 协议规定最多可以用四个字节来标识包长度。

所以这四个字节最多可以标识的包长度为:(0xFF, 0xFF, 0xFF, 0x7F) = 268435455 字节,约 256M,这个是 MQTT 协议中数据包的最大长度。

注意:Remain Length 的值不包含固定头的大小,包括第 1 字节和 Remain Length 字段。

1.5 小结

我们在这一课中学习了 MQTT 的通信模型,以及 Client 和 Broker 的概念,同时也学习了 MQTT 数据包的格式。接下来我们开始收发数据的第一步:从 Client 连接到 Broker。

相关资料:

  • MQTT Client 库在多种语言中的库实现

点击了解更多《MQTT 协议快速入门》

第02课:建立到 MQTT Broker 的连接(一)
第03课:建立到 MQTT Broker 的连接(二)
第04课:订阅与发布(一)
第05课:订阅与发布(二)
第06课:QoS0 和 QoS1
第07课:QoS2 和 QoS 的最佳实践
第08课:Retained 消息和 LWT
第09课:Keep Alive 和连接保活
第10课:实战 IoT+AI(一)
第11课:实战 IoT+AI(二)
第12课:搭建 MQTT Broker 和安全实践
第13课:MQTT 5.0 协议新特性
附录:常见问题解答

阅读全文: http://gitbook.cn/gitchat/column/5be4f4df2c33167c317beb8c

你可能感兴趣的:(MQTT 协议快速入门)