如果你耐着性子从第一节看到这里,那么恭喜你,你现在已经准备好构建一个属于自己的物联网平台了。
我们现在来总结一下在本课程中学到的东西。

从 Client-Broker-Client 到 Client-Server

在本课程中,我们通过抽象,将 MQTT 的 Client-Broker-Client 模式转换成了 Client-Server 模式。对于设备而言,它通过调用 DeviceSDK,不用再去关心底层的数据传输细节,只用关心向服务器发送数据和处理服务器下发的数据。对于业务系统来说,它通过调用 IotHub 提供的 API,不需要再建立到 Broker 的连接,只关心处理设备上报的数据和下发数据到设备。至于数据是用 MQTT 还是 CoAP,MQTT Broker在哪里,对 Client-Server 模式都是透明的。我们主要是通过以下两点完成这个抽象的。

主题规划

在 IotHub 中我们定义了一系列的主题,我们把主题当作描述消息内容的元数据字段在使用。这是很关键的一点,如果说我们把消息的描述放入 Payload 的话,那 IotHub 的业务逻辑就和设备应用代码的逻辑耦合到一起了。要记住的是,在 MQTT 或者任何类似队列的系统里,用 Payload 来判断消息的类型,都是 anti-pattern。 在这样的系统里面,应该是用主题名或者队列名来进行消息类型的判断,同一种类型的消息应该使用同样的主题名或者队列名。
IotHub 利用了 EMQ X 的 Hook 机制,在处理上行数据时,设备 Publish 的 MQTT 消息中的主题实际上是没有任何真实的 MQTT Client 在订阅的,EMQ X Broker 不再通过主题名将消息路由给其他的 Client,而是将消息交给 IotHub Server 进行处理,这样就更像一个 C/S 模式的服务器,而不是 Broker 了。
在处理下行数据时,主题名除了描述消息内容以外,还有路由的功能,这是必须的。

IotHub作为中间件

IotHub 或者说物联网平台很重要的一个设计思路是,作为业务系统和设备之间的中间件,IotHub 的目的是通过复用业务逻辑来简化和加快物联网应用的开发。对业务系统和设备屏蔽掉底层的协议细节,并提供一些常用的基础功能:

  • OTA升级
  • 指令下发
  • 数据上报
  • 设备认证与管理
  • 设备分组
  • 影子设备
  • NTP服务

那么基于 IotHub 开发一套物联网应用,就只需要关注于业务逻辑的实现就可以了。你的公司再开发新的物联网应用都可以基于 IotHub,业务系统可以复用 IotHub 的 Server API,设备端也可以直接复用 DeviceSDK 的代码,如果换了平台,只需将 DeviceSDK 移植到相应语言上就可以了。

EMQ X 的高级功能

本课程中我们使用一些 EMQ X 的功能,这些功能是 MQTT 协议没有指定的,它们简化了 IotHub 的开发,扩展了 IotHub 的功能。
灵活的 Client 认证: EMQ X 提供了多种认证机制,本课程使用的是 MongDB 和 JWT,你也可以根据你的具体需求更换为其他认证方式,多种认证方式可以组成认证链。如果自带的认证方式无法满足你的需求,你还可以通过编写插件来自行扩展。

建议保留 JWT 认证方式

基于插件的 Hook 功能: 通过 Hook 机制,IotHub Server 不再需要通过订阅的方式来获取设备的消息了,除了自带的 Hook 插件,我们还学习了如何编写插件,并实现了一个基于 RabbitMQ 的 Hook 插件。
管理和监控:通过使用 EMQ X 提供的 API,可以不用在建立 MQTT 连接的前提下发布数据,同时也可以对设备的连接进行管理,强制关闭设备连接;通过订阅 EMQ X 提供的系统主题,可以对 Broker 的运行状态进行监控。
服务器订阅: 通过使用服务器订阅,简化了设备端的代码,并且减少了设备端需要发送的 Subscribe 消息。

当然使用设备端订阅,在设备每次上线的时候订阅相应主题也是可行的,不过你要注意的是,这样做有两个缺点,第一,大多数时候设备上线发送的 Subscribe 包都是多余的;第二,重复订阅主题对 Retain 消息处理是有干扰的,每次订阅的时候都会收到主题上的 Retain 消息,这与Retain 消息设计的初衷是相违背的。 如果这两个缺点对你来说没有什么影响,你可以根据你的需求选择使用设备端订阅。

不只是 MQTT

MQTT 是目前最流行的物联网协议,不过它不是在任何情况下都是最优的。IotHub 除了支持 MQTT 协议以外,还支持 CoAP 协议的接入。目前比较常见的物联网协议还有 MQTT-SN、LWM2M 等,有需求的话都可以自行学习和扩展。

EMQ X 还支持 MQTT-SN 和 LWM2M。

离生产环境运行还有多远?

本课程中我们实现了一个功能相对完善的物联网平台,那么我可以将这个平台直接用到生产环境中去吗? 答案是否定的,我们来看一下离生产环境使用还差多远:

完成剩下的70%的代码

我们都知道,一般来说,在一个软件项目中,只有 30% 的代码是完成业务功能的,而其他 70% 的代码都是在做错误处理。在本课程中,因为篇幅有限,基本就跳过了这70%的错误处理代码,把内容集中在了展示功能设计和实现上。所以要在生产环境使用这套代码,还需要补上错误处理的部分。
Node.js 并不是我常用和熟悉的语言,我的初衷是选择一门流行的、受众比较广而且简单的语言来表达 IotHub 的设计思路,所以在编程的技巧上这可能不是最优的。但是 IotHub 的架构和功能设计思路应该表达清晰了,你可以按照你的实际情况,把 IotHub 的移植到你熟悉的语言上,并对功能进行裁剪或者扩展。
DeviceSDK 也需要按照你的实际情况移植到对应的语言上,毕竟使用 Node.js 的物联网终端还是比较少的。

横向扩展

在生产环境中部署 IotHub 还需要考虑横向其扩展性,IotHub 在设计之初就考虑到这点,它的每一个组成模块都是可以横向扩展的。
EMQ X: 可以组成集群,以下是一个双节点 EMQ X 集群的推荐部署方式:
46.我们学到了什么? - 图1
Monitor: monitor使用的是共享订阅,所以可以启动多个 Monitor 进程来实现负载均衡。
Event_Handler: RabbitMQ 是支持多消费者的,可以启动多个 Event_Handler 进程来实现负载均衡。
Server API: 可以像横向扩展任意 Web 服务的方式进行扩展。
Redis: 可以组成 Redis Cluster。
MongoDB: 可以组成 MongoDB Replica Set。
InfluxDB: 可以组成 InfluxDB cluster。
RabbitMQ: 可以组成 RabbitMQ Cluster。

致谢

最后在这里感谢大家耐心学完本课程,因为课程编写的时间仓促,本人的水平也有限,课程中难免有纰漏,也希望大家多多指正。可以加入本课程的讨论群一起讨论,学习和进步。