你好,我是郭朝斌。

在上一讲中,我为你介绍了物联网设备常用的几种无线通信技术。通过这些技术联网之后,物联网设备就可以向云平台上报数据了吗?还不可以。

成功传输数据的前提是,通信双方必须使用同一种“语言”。这就像,你拨通了比尔·盖茨的电话,如果说“喂,你好”,他大概会一头雾水;但如果说“Hello!”,他一下就能听懂了。

而物联网设备间沟通的语言,就是网络协议。说起网络协议,你可能马上就想到了 HTTP 协议。是的,在日常的 Web 开发中,我们总是需要跟它打交道,因为 HTTP 协议是互联网的主流网络协议。

类似地,应用在互联网中的网络协议,还有收发电子邮件的 POP3、SMTP 和 IMAP 协议,以及用于区块链中的 P2P 协议。

那你马上会问了,物联网设备之间的通信,可以直接使用这些协议吗?

物联网通信的特点

想要回答这个问题,我们得先来分析一下物联网的网络通信特点。

  1. 物联网设备很大可能工作在不可靠、高延迟的网络环境中。

比如共享单车,使用 NB-IoT 这样的通信技术,本身的通信速率就只有不到几十 Kbps;要是被人停在城市的角落里,信号可能很不稳定。

假设你使用 HTTP 协议,就需要单车先发出连接请求,然后等待服务器的响应(下发开锁指令)。这样一来,受网络通信质量的影响,很可能连接经常中断,而需要单车与服务器交互多次,那用户可能就要等很长时间。

对于这种场景来说,不只是 HTTP,其他跟 HTTP 一样单向的、同步的网络协议,都不是理想的技术方案。

  1. 物联网系统中,设备数量多, 而且 交互非常复杂

比如你家里的环境监测,温度、湿度、光照、二氧化碳、甲醛含量……这些都需要不同的设备测量,而且每个房间用到的设备也不同。

如果你让云平台的服务对每个设备分别做权限控制和数据阈值设置,这会非常麻烦。因为当数据的“生产者”和“消费者”直接交互时,要是没有中间角色基于共同的目标协调,双方的耦合度会很大,导致系统很难实现。

这时候,你需要把你家作为一个整体来处理,交互逻辑就会变得简单多了。

  1. 设备经常需要根据实际使用环境做增加、减少等调整

比如你用一个设备测量房间的温度,现在这个设备损坏了,你要换一个。你肯定不希望因为设备 ID 这么一个小小的变化,就要去修改判断房屋温度的逻辑代码,这太麻烦了,也不符合软件开发的开闭原则。

这要求系统必须具备可伸缩性(或者说可扩展性),设备的增减不会导致系统逻辑的调整。

正是因为这些特点,物联网系统在选择网络通信的协议时,一般采用发布 - 订阅的通信模式。为什么说发布 - 订阅模式适合呢?我来解释一下它的设计,你就明白了。

发布 - 订阅模式

发布 - 订阅模式包含三个角色,分别是发布者(Publisher)、经纪人(Broker)和订阅者(Subscriber),它们的关系如下图所示。

三个角色之间的消息传递,基于一个重要的概念——主题。主题用于消息的过滤(或者说路由),它确定了消息的不同类别。消息传递的过程可以分为三步:

  1. 发布者负责生产数据。发布者发送某个主题的数据给经纪人,发布者不知道订阅者。
  2. 订阅者订阅经纪人管理的某个或者某几个主题。
  3. 经纪人接收到某个主题的数据时,将数据发送给这个主题的所有订阅者。

我们举个例子你就理解了。到中午了,你有点饿。今天吃什么呢?你想了想,拿出手机打开外卖 App,选择了牛二楠家的咖喱牛肉盖饭,外加双份肥宅快乐水加冰。

当你发布牛二楠家的订单给外卖订单中心服务器时,隔壁的产品经理小王也在点外卖,他点了猪三排家的红烧排骨盖饭。

外卖订单中心收到这两个订单之后,会把你的订单发送给牛二楠家,把小王的订单发送给猪三排家。

相信你也看出来了,你和小王都是“发布者”,牛二楠家和猪三排家就是“订阅者”,而外卖订单中心就是“经纪人”。

当然,你内心可能在祈祷外卖订单中心出个错,把小王那个订单(猪三排家的红烧排骨盖饭)发送到做卤煮的猪三下水家那里,给他的午饭增加一点难忘的体验。

为什么我说发布 - 订阅模式适合物联网系统呢?因为在物联网场景中,一个传感器数据需要触发多个服务或者终端执行动作

比如红外传感器,当它检测到有人体靠近时,就需要触发一系列动作:通知摄像头拍照,声光报警器执行报警,推送消息给主人的手机等。

怎么满足这种需求呢?我们最好让摄像头、声光报警器和手机都订阅“人体靠近”这个主题消息。当红外传感器被触发时,它发送人体靠近的消息,然后这些设备就能同时收到这个消息,接着完成系统定义的那些动作。这就是发布 - 订阅模式的工作方式。

另外,发布 - 订阅模式减少了发布者与订阅者之间的耦合度,所以网络不稳定导致的临时离线就不会影响彼此的工作。它的拓扑结构也使系统更容易扩展,更容易满足动态变化的需求。这些优点都使得发布 - 订阅模式在物联网应用协议中非常流行。

那么,具体有什么网络协议采用的是发布 - 订阅通信模式呢?MQTT 协议就是其中的佼佼者。

MQTT

MQTT(MQ Telemetry Transport)协议,是 IBM 公司在 1999 年开发的轻量级网络协议,它有三个主要特点:

  1. 采用二进制的消息内容编码格式,所以二进制数据、JSON 和图片等负载内容都可以方便传输。
  2. 协议头很紧凑,协议交互也简单,保证了网络传输流量很小。
  3. 支持 3 种 QoS (Quality of Service,服务质量) 级别,便于应用根据不同的场景需求灵活选择。

这里我解释一下什么是 QoS。它是指通信双方关于消息传送可靠程度的协商。QoS 0,消息只发送一次,消息可能丢失;QoS 1 呢,发送方会接收反馈,保证消息的送达,但是可能消息会重复。QoS 2 级别,通过发送方和接收方的多次交互,保证消息有且只有一次。

现在我们说回 MQTT。刚才提到的这三个特点,让 MQTT 协议非常适合计算能力有限、网络带宽低、信号不稳定的远程设备,所以它成为了物联网系统事实上的网络协议标准。关于 MQTT 协议的详细内容,我还会在进阶篇第 8 讲为你进一步剖析。

AMQP

除了 MQTT 协议以外,也有其他采用发布 - 订阅模式的网络协议,比如 AMQP 协议。

虽然 AMQP 协议拥有庞大的特性集,比较重,不适合计算资源有限、对功耗要求严苛的物联网设备,但是它可以满足后台系统对于可靠性可扩展性的要求。因此,它在物联网的平台系统中应用广泛。比如,在分布式系统中应用广泛的 RabbitMQ 消息中间件软件,就是基于 AMQP 实现的。

AMQP 和 MQTT 一样,也是基于 TCP 协议,采用二进制消息格式,也支持 3 个 QoS 级别。

顺带说一句,现在被广泛使用 AMQP 1.0 和 AMQP 0.9.1 这两个版本,在设计上有很大的差异。你在查询资料或者应用这两个版本的 AMQP 协议时,一定要注意看版本,避免用错。

请求 - 响应模式

刚才我介绍了发布 - 订阅模式的很多好处,但是凡事都有例外,也有一些物联网应用场景,并不适合使用这种模式。

比如,现在小区里面都有智能快递柜,当你输入取件码后,服务器会向对应的柜门发送开门指令。

在发布 - 订阅模式下,服务器知道指令发送成功了,但是它无法知道柜门是否真的打开了。这时,你就需要让柜门能够向服务器反馈一下命令的执行结果。

当然,你也可以让服务器订阅一个“柜门关闭”的主题消息,然后等待柜门发布这个消息。但是这样的话就非常繁琐、不够直接。

在这种场景下,另一种通信模式就能派上用场了,那就是请求 - 响应模式。

请求 - 响应模式有两个角色,一个是客户端(Client),另一个是服务器(Server)。

客户端是请求数据或者服务的一方。服务器则用来接收客户端的请求,并提供相应的数据或者服务。服务器在收到请求后,会获取数据,对资源数据(比如数据库)进行加工处理,准备好响应,然后返回给客户端。

请求 - 响应模式是无状态的通信方式,每个完整的请求 - 响应都是相互独立的。进一步细分的话,它还可以分为同步和异步两种。你可以看下这张图片。

我们还是以外卖来举例。当你拿出手机点好外卖后,牛二楠家的服务员会收到外卖订单,然后通知厨师准备盖饭,同时另一个服务员已经熟练地打好了快乐水。

半个小时后,外卖小哥拿着装有你心仪午餐的袋子出现在公司门口,然后交到你的手里。他满脸笑容地说,闯了 2 个红绿灯才这么快送到,希望你给个好评。

这就是请求 - 响应模式。你是“客户端”,牛二楠家是“服务器”,你发出“请求”后,等待一段时间,然后外卖小哥将“响应”给到你。流程如下面的图片所示:

HTTP

有哪些网络协议采用了请求 - 响应模式呢?HTTP 就是典型的代表。HTTP/2 协议还引入了异步请求 - 响应模式,客户端可以对请求设置不同的优先级,服务器可以根据优先级决定先响应哪个请求。

虽然 HTTP 协议的报文格式非常重,光是报文头就能达到 KB 大小,不太适合资源有限的嵌入式设备。但在一些计算资源和网络资源都比较充足的物联网设备上,HTTP 协议仍然是一个可选项。而且它和现有的 Web 系统兼容,可以利用已有的 Web 服务器资源。

CoAP

那么有没有跟 HTTP 协议类似,但是设计轻量,可以用于资源受限的物联网设备的协议呢?

有的,那就是 CoAP(Constrained Application Protocol)协议。

跟 HTTP 协议一样,CoAP 协议同样有 GET、POST、PUT、DELETE 等方法和响应状态码,同样使用 URI 而不是 Topic 来标识资源。

比如我们需要访问服务器 iotdemo.com 下面的 bedroom/temp 这个资源,那完整的资源地址是:

coap://iotdemo.com:5683/bedroom/temp

CoAP 的消息采用二进制格式,支持可确认消息和不可确认消息两种 QoS 级别。可确认消息(Confirmable Message)与 MQTT 协议的 QoS 1 类似,不可确认消息(Non-confirmable Message)对应 MQTT 协议的 QoS 0 级别。

另外,CoAP 协议基于的传输层协议是 UDP,而不是 HTTP、MQTT 协议的 TCP 协议,所以对于设备的计算资源要求更低。传感器设备一般只需要上传数据,不用随时接收服务器的控制命令,这都说明 CoAP 协议适合电池供电的传感器设备。

LwM2M

说完 CoAP,我再介绍一下跟它有关 LwM2M(Lightweight M2M)协议。

LwM2M 协议定义在 CoAP 协议之上,不过它在消息传输的基础上更进一步。因为它基于 IPSO(IP-base Smart Object)对设备模型进行了标准化,提供了一组轻量级设备管理和交互接口协议。

LwM2M 协议目前主要的实现是 C 语言的 Wakaama 和 Java 语言的 Leshan,相对来说应用还比较少。CoAP 协议的应用场景同样适合 LwM2M 协议,如果你希望在 CoAP 协议的基础上更方便地实现设备的管理,可以考虑 LwM2M 协议。

通信模式的共存

到这里呢,我就讲完了“发布 - 订阅模式”和“请求 - 响应模式”的各自特点,以及相应的网络协议。那你可能会问,有没有网络协议可以同时拥有这两种通信模式呢?有这种想法,说明你非常善于独立思考。确实,这样也更能满足实际场景的需求,而且从原理上看,也完全可以实现共存。

现在行业内也意识到了这一点,所以一些网络协议已经纷纷做出了尝试。比如 MQTT 5.0 中增加了请求 - 响应模式的新特性;AMQP 1.0 版本也定义了请求 - 响应模式。而 CoAP 协议呢,在新的初稿版本(Draft)中也增加了发布 - 订阅模式特性。

这种网络协议中的通信模式的共存,相比单一模式的设计都大大方便了具体场景中的应用,代表了一种网络协议的发展方向。

小结

在这一讲中,我对比了“发布 - 订阅”和“请求 - 响应”这两种主流的通信模式,并简单介绍了两种通信模式下的网络协议。

物联网应用是一个复杂的综合性系统,这要求你了解不同网络协议的功能特性和局限,并且为系统的不同部分做出合适的选择。这些选择原则,我总结为下面三点:

  1. 物联网设备通常需要运行在网络不太可靠的环境中,而且在功耗、体积和计算资源方面也有诸多限制,所以我们在设备的开发中可以考虑使用 MQTT 和 CoAP 协议。
  2. 云平台各服务之间需要快速、可靠地进行消息转发,这种情况可以选择 AMQP 协议。
  3. 一些应用需要兼容 Web 系统的 RESTful 架构,比如通过 REST 开放物联网中的资源能力,供其他应用调用,这时 HTTP 和 CoAP 协议是合适的选择。

我在这里再提供一个网络协议的思维导图,供你参考。

思考题

最后,我想给你留个问题。你还知道有哪些协议,适合用在物联网系统中吗?它们又是采用了哪种通信模式呢?

欢迎你在留言区写下你的答案,和我交流一下,也欢迎你将这一课分享给你的朋友,共同交流学习。