随 JavaScript 语言的流行,及物联网领域的崛起,我们能看到它们结合的可能性,同时也发现它特别适合于物联网开发。因此,在这篇文章里,笔者将主要从以下三个方面进行介绍:
- 典型的物联网架构,及多种语言带来的问题;
- 只使用 JavaScript 语言的物联网架构;
- 详解基于 JavaScript 语言的物联网不同层级结构。
那么,先让我们看看典型的物联网架构是怎样的吧。
典型的物联网架构
我们甚至还可以认为,物联网只是对互联网的扩展。与传统的 C/S 架构相比,它多了一个“数据采集层”,我们称之为传感器层、硬件层等。数据的产出不再只是用户,还来自于各式各样的联网设备。物联网不再局限于使用 HTTP 协议来传输数据,它还会使用 CoAP(受限制的应用协议)、MQTT(消息队列遥测传输)协议。
物联网的四个层级
当前的物联网应用,所要做的就是控制和数据处理。指令,由用户到终端一层一层往下下达,直到硬件端由设备去执行。而数据,便是一层一层往上上报,直至被可视化。
因此,与互联网的架构相比(如图 1、图 2 所示),起点与终点不一样了:指令的终点与数据的起点,变成了硬件层,而非最后的用户层。
数据由客户端 A 发送到服务端,客户端 B 再从服务端获取 A 的数据,如此便算是完成了一个回路。而物联网架构则稍微麻烦了一些,多了一个层级,便多了一个步骤。
硬件层上的微控制器通过直连的方式,采集各式各样的数据,比如温度、湿度等。而受限于微控制器的成本、环境条件等因素,它可能无法直接连接到互联网。因此,需要连接到一些额外的联网设备才能实现。
而这些联网设备,会负责处理来自各个硬件设备的数据,并将其上传至服务器。同时,它会提供一个无线(如蓝牙、红外、ZigBee)接口作为数据的入口。因此,这一层级需要有更好的数据处理能力,并且它应该要可以快速开发。因为这些设备主要做的是协调工作,我们习惯于将其称为“协调层”。
使用多种语言的物联网
多年以前,笔者曾做过一个并不复杂的物联网系统:
- 使用 Python 里的 Django 作为 Web 服务框架,Django REST Framework 创建 RESTful API;
- 为了使用手机作为控制器,还用 Java 写一个 Android 应用;
- 使用 Raspberry Pi 作为硬件端的协调层,用于连接网络,并传输控制信号给硬件;
- 在硬件端使用 Arduino 作为控制器,写起代码特别简单;
- 还使用了 ZigBee 模块 XBee 及 I2C 作为连接不同 Arduino 模块的介质;
- 最后,还需在网页上做一个图表来显示实时数据。
为此,我们需要使用 Python、Java、JavaScript、C、Arduino 五种语言。而如果我们要写相应的 iOS 应用,还要用到 Objective-C。对于其他物联网项目来说,也多是如此,这简直是一场灾难。
在做这样的物联网项目之前,我们需要找到六个不同类型的工程师:一个硬件工程师设计电路图,一个懂硬件的嵌入式工程师,一个写服务端应用的工程师,一个写 Web 前端的工程师,以及对应的 Android 和 iOS 工程师。
且不考虑系统本身的协作,要找到这么多的工程师就不是一件容易的事。而如果我们可以只使用一种语言,将大大地改善开发效率、开发人员的难题。
JavaScript 语言下的物联网架构
JavaScript 语言在最近几年里特别流行,它流行起来有很多个原因,如:
- 使用 WebView 开发 UI 效率更高,也因此使得 WebView 随处可见;
- 基于事件驱动的编程模型;
- JavaScript 容易上手(这是优点,也是缺点);
- 也因此,React、Unity 等框架提供了更多的可能性,可以让开发者用 JavaScript 开发游戏、VR 应用等等。
那么,只使用 JavaScript,我们可以设计出怎样的物联网系统呢?
基于纯 JavaScript 的物联网架构
如上所述,几年前要想寻找一门能完成一个包含客户端、服务端的系统的语言可谓相当地困难。而随着客户端(浏览器、移动设备)性能的提升、Node.js 的出现,这样的语言就浮现了出来,即 JavaScript。它不仅可以让我们只用一门语言来降低开发成本,还能实现快速地开发出这样的一个系统。那么,剩下的问题就是,在不同的层级,如何选用合适的框架来实现快速开发。
如图 3 所示,我们可以看到不同层级的可选用 JavaScript 方案。在此之中,有些纯粹只是为了证明 JavaScript 是可行的;有一些则可以在开发效率与运行速率上达到最好的平衡。选用这些方案,可以让我们实现更快速的 JavaScript 物联网应用开发。
服务层
对于服务层来说,自主开发的物联网服务端,主要采用的是基于 Node.js 的方案。然而,我们发现有越来越多的应用,在使用 Serverless 的架构,不仅可以快速推出一个可用的原型,未来也能够轻松地基于这个原型来添加业务功能。
图 4 便是我们看到的物联网服务层的三种方案:
- 自主开发:即遵循传统的服务端开发模式,定义自己所需要的功能;
- 使用云服务:直接使用成熟的物联网云服务,它们在云端集成了各种所需要的功能;
- Serverless:Server 可以看作是在云服务之上的自主开发,集两者之便利。
每一种方案都有各自的特点,也适合于不同开发能力的项目。但如果要实现快速的开发,那么理想的方式便是采用 Serverless 架构模式。
自主开发
出于不同的原因,诸如保密、安全、可扩展、核心技术等原因,一定规模的公司会采用自主开发的方式。这种开发方式与 Web 应用开发方式并没有太大区别,都是在数据进行 CRUD 操作。并且和前后端分离架构一样,使用 API 作为接口,同时再加上支持不同的传输协议,如 MQTT、CoAP 等。
如笔者之前在 GitHub 上开源的 Lan(https://github.com/phodal/lan),便是一个精简的物联网服务端示例。基于 Node.js 与 MongoDB,其架构如图 5 所示。
- 采用传统的关系型数据库来存储用户信息;
- 采用 NoSQL 可以应对不同的传感器数据;
- 提供 UI 界面供管理人员管理用户;
- 在协议上提供 HTTP、CoAP、MQTT、WebSocket 等的支持,方便不同的类型适配。
除此,物联网系统在存储上,采用 NoSQL 作为存储介质会有更大的优势。一般来说,物联网系统的数据都是写入远远多于读取的场景。与此同时,由于设备的种类繁多,不可能为每一类设备创建表;或者考虑到大量设备的特性,来建立一个通用的表,但在未来这样的表可能仍不适用。
因此,对于物联网数据来说,选用诸如 MongoDB 这一类的 NoSQL 数据库,有这么一些优点:
- 灵活性。采用非结构化的数据模型,可以存储和处理任何结构的数据;
- 支持水平扩展。NoSQL 数据库的分布式存储架构,带来了优秀的水平扩展性;
- 实时数据分析。如 MongoDB 可以通过丰富的索引和查询支持,包括二次、地理空间和文本搜索索引,聚合框架和本地 MapReduce,可以针对传感器数据就地运行报告分析。
然而,这样的系统不免存在研发周期长的问题。如果需要快速验证,那么应该考虑使用云服务来完成部分功能。
物联网云服务
对于硬件团队来说,直接使用云服务是一种更简单、快速的搭建物联网系统的方法。而使用物联网云服务,就意味着:我们可以直接上硬件层的传感器数据,并在应用层获取、分析这些数据。这一类的服务,比较成熟的有 AWS IoT Things(如图 6 所示)、Azure IoT 等。
基于 AWS IoT Things,我们只需要在云端,定义好对应的数据处理规则,便可以在硬件端直接对接服务。不过值得注意的是,单一的云服务无法提供复杂的功能,这个时候就需要一些搭配额外的服务。
Serverless
Serverless 架构(如图 7 所示)是云服务的一种,但是它在可编程与云服务之间做了一个折中。它是一种基于互联网的技术架构理念,应用逻辑并非全部在服务端实现,而是采用 FaaS(Function as a Service)架构,通过功能组合来实现应用程序逻辑。
从理论上来讲,这些服务提供的是一层 API 封装,它不会限制我们所使用的语言。使用 Serverless 服务,我们可以具备更好的快速开发能力,并且能使用同一种语言(JavaScript)来完成编程。
在这个过程中,开发者要所做的便是:在不同的服务之间传输数据,每一次都只处理下一个服务所需要的数据,类似于 Pipe and Filters 架构模式。如一个典型的物联网应用的数据传输过程中是这样的:
- 对设备进行鉴权;
- 转换、存储设备的数据;
- 广播通知其他监听此设备数据的服务;
- 后台查询数据;
- 分析数据(AI);
- 可视化数据。
只需要少量的编程,我们就可以完成服务端的开发。随后,专注于硬件层的开发,以及应用层的业务功能。
应用层
在应用层方面,已经有大量的地方使用到了 JavaScript。除了传统的桌面浏览器,还有更多的领域也可以用 JavaScript 来开发。比如移动应用,已经有基于 Cordova + WebView 的成熟方案,还有近两三年流行起来的 React Native,都可以让开发者使用 JavaScript 完成物联网移动应用的开发。又如微信小程序,可以直接用蓝牙来连接硬件设备,也是使用 JavaScript 来编程。
因此,就目前的 Web 趋势来看,在应用层,JavaScript 将是快速开始的主流选择。
在日常中的应用中,我们可以发现物联网的应用层,经常作为协调装置来连接硬件,并上传应用的数据。诸如共享单车、智能手环应用等,它们既通过蓝牙来获取数据,又上传数据到服务端。与此同时,有相当多的应用是运行在桌面客户端上的。故而在这一层级的应用,可谓是种类繁多。
今天,开发人员在做移动端的技术选型时,都会优先考虑到跨平台能力(Android、iOS)。而在这些跨平台框架里,混合应用框架 Cordova(WebView)和 React Native 是使用最为广泛的两个框架,且它们都是使用 JavaScript 作为核心开发语言。
Cordova 是使用 WebView 来渲染页面的。因此与 Reavt Native 相比,使用 Cordova 的最大优势是,可以复用已有的 Web 前端应用的逻辑,并且有大量的图表工具可以直接使用——这一点在物联网应用中特别重要。而在混合应用框架中,Ionic 是这个领域使用最多的 UI 框架。
React Native 使用原生组件来渲染 UI 组件,不仅可以解决 Cordova 饱受诟病的性能问题;同时,它还能嵌入 WebView,解决一些复杂的图表显示问题。
但是如果只能蓝牙的交互,可以考虑 PWA 或微信小程序。运行在 Chrome 浏览器上的 PWA 应用,可以直接使用 Web Devices API,如 Bluetooth、NFC、USB,即在浏览器上直接调用原生接口,并实现对设备的控制。而诸如最近一年内流行的微信小程序,则也可以访问蓝牙、GPS、罗盘、加速度计等硬件接口,同时用户不存在安装成本,打开即用。
另外,诸如 Electron、NW.js 这样的框架,可以让开发者直接使用 WebView + Node.js 模块开发物联网桌面应用。它可以加速 UI 界面的开发,并轻松地美化 UI 界面。
硬件层
在硬件层上,就当前而言,Arduino 是最合适的原型开发硬件,除此还有自带 Wi-Fi 的 ESP8266 开发板。尽管使用 JavaScript 的开发板数量较少,也没有 Arduino 这样的成熟生态,但是未来可期。在嵌入式领域,使用 JavaScript 编写的代码,具有移植性强、事件驱动、天生支持异步等特点。
令人遗憾的是,为了保持上面提到的那些 JavaScript 特性,当前的 JavaScript 开发板都需要处理性能比较高的处理器,这也导致了此类开发板在生产上存在较高的成本。不过,好在多数使用 JavaScript 作为开发语言的设备,都具有网络功能连接到互联网,直接作为物联网设备使用。
就目前而言,这一类的设备有 Tessel、Espruino、Ruff 等等,它们的处理器性能都相当不错,价格也相对较高一些。但是,它们可以直接使用 JavaScript,能为软件开发工程师屏蔽底层相关细节,及事件驱动、异步特性,带来更好的开发体验。
幸运的是,Samsung 公司推出的开源物网框架 IoT.js,只需要 64KB RAM、200 KB ROM。在未来,或许它能解决一些制造成本上的问题。
协调层
当我们的硬件层不能直接联网时,协调层就可以完成这样的功能。作为一个协调层的设备,它应该能与一定数量的微控制器连接,接收它们的数据,并上传到服务端;又能与服务端通讯,获取一些控制指令,并将这些指令准时地发送给不同的控制器。所以,它需要有更好的处理能力、更多的 RAM、ROM 等等。因此,在这一层级使用 JavaScript 便不存在成本问题。我们只需要使用和服务端、应用层相似的知识,就可以快速地连接设备到网络中心。还能直接在本地的 Linux 机器上编写代码,并无缝地运行在设备上。
这一类应用,依赖于 Node.js 引擎来实现快速开发。它可以运行在带有嵌入式系统的开发板上,如流行的 Raspberry Pi、OpenWRT 路由器等。
我们只需要一个运行嵌入式 Linux 系统的开发板,就可以完成这样的工作。与此同时,主流的 ARM 开发板都提供相应的 Linux 移植,因此在这个层级,我们也只需要关注于业务的实现。
小结
如上所述,物联网应用的架构与 Web 应用的架构区别并不是太大,只是在这上面做一系列的演进。除了上面提到的一系列快速实践框架,当前在 Web 开发中流行的一些开发思想,势必也会引导到物联网系统中:
- 微服务化;
- DevOps;
- 容器化。
物联网会吸引互联网的优秀开发思想,并演进出更优秀的架构。
作者:黄峰达,ThoughtWorks 软件开发工程师,CSDN 博客专家。长期活跃于 GitHub,专注于物联网和前端领域。出版著作《自己动手设计物联网》,以及《Growth:全栈增长工程师指南》等六本电子书,并译有《物联网实战指南》。
责编:唐门教主,欢迎技术投稿、约稿、给文章纠错,请发送邮件至tangxy@csdn.net。
声明:本文为《程序员》原创文章,未经允许不得转载,更多精彩文章请订阅2017 年《程序员》。