基于JavaScript語言的快速物聯(lián)網(wǎng)開發(fā)架構
隨 JavaScript 語言的流行,及物聯(lián)網(wǎng)領域的崛起,我們能看到它們結合的可能性,同時也發(fā)現(xiàn)它特別適合于物聯(lián)網(wǎng)開發(fā)。因此,在這篇文章里,筆者將主要從以下三個方面進行介紹:
- 典型的物聯(lián)網(wǎng)架構,及多種語言帶來的問題;
- 只使用 JavaScript 語言的物聯(lián)網(wǎng)架構;
- 詳解基于 JavaScript 語言的物聯(lián)網(wǎng)不同層級結構。
那么,先讓我們看看典型的物聯(lián)網(wǎng)架構是怎樣的吧。
典型的物聯(lián)網(wǎng)架構
我們甚至還可以認為,物聯(lián)網(wǎng)只是對互聯(lián)網(wǎng)的擴展。與傳統(tǒng)的 C/S 架構相比,它多了一個“數(shù)據(jù)采集層”,我們稱之為傳感器層、硬件層等。數(shù)據(jù)的產(chǎn)出不再只是用戶,還來自于各式各樣的聯(lián)網(wǎng)設備。物聯(lián)網(wǎng)不再局限于使用 HTTP 協(xié)議來傳輸數(shù)據(jù),它還會使用 CoAP(受限制的應用協(xié)議)、MQTT(消息隊列遙測傳輸)協(xié)議。
物聯(lián)網(wǎng)的四個層級
當前的物聯(lián)網(wǎng)應用,所要做的就是控制和數(shù)據(jù)處理。指令,由用戶到終端一層一層往下下達,直到硬件端由設備去執(zhí)行。而數(shù)據(jù),便是一層一層往上上報,直至被可視化。
因此,與互聯(lián)網(wǎng)的架構相比(如圖 1、圖 2 所示),起點與終點不一樣了:指令的終點與數(shù)據(jù)的起點,變成了硬件層,而非***的用戶層。
數(shù)據(jù)由客戶端 A 發(fā)送到服務端,客戶端 B 再從服務端獲取 A 的數(shù)據(jù),如此便算是完成了一個回路。而物聯(lián)網(wǎng)架構則稍微麻煩了一些,多了一個層級,便多了一個步驟。
硬件層上的微控制器通過直連的方式,采集各式各樣的數(shù)據(jù),比如溫度、濕度等。而受限于微控制器的成本、環(huán)境條件等因素,它可能無法直接連接到互聯(lián)網(wǎng)。因此,需要連接到一些額外的聯(lián)網(wǎng)設備才能實現(xiàn)。
而這些聯(lián)網(wǎng)設備,會負責處理來自各個硬件設備的數(shù)據(jù),并將其上傳至服務器。同時,它會提供一個無線(如藍牙、紅外、ZigBee)接口作為數(shù)據(jù)的入口。因此,這一層級需要有更好的數(shù)據(jù)處理能力,并且它應該要可以快速開發(fā)。因為這些設備主要做的是協(xié)調工作,我們習慣于將其稱為“協(xié)調層”。
使用多種語言的物聯(lián)網(wǎng)
多年以前,筆者曾做過一個并不復雜的物聯(lián)網(wǎng)系統(tǒng):
- 使用 Python 里的 Django 作為 Web 服務框架,Django REST Framework 創(chuàng)建 RESTful API;
- 為了使用手機作為控制器,還用 Java 寫一個 Android 應用;
- 使用 Raspberry Pi 作為硬件端的協(xié)調層,用于連接網(wǎng)絡,并傳輸控制信號給硬件;
- 在硬件端使用 Arduino 作為控制器,寫起代碼特別簡單;
- 還使用了 ZigBee 模塊 XBee 及 I2C 作為連接不同 Arduino 模塊的介質;
- ***,還需在網(wǎng)頁上做一個圖表來顯示實時數(shù)據(jù)。
為此,我們需要使用 Python、Java、javascript、C、Arduino 五種語言。而如果我們要寫相應的 iOS 應用,還要用到 Objective-C。對于其他物聯(lián)網(wǎng)項目來說,也多是如此,這簡直是一場災難。
在做這樣的物聯(lián)網(wǎng)項目之前,我們需要找到六個不同類型的工程師:一個硬件工程師設計電路圖,一個懂硬件的嵌入式工程師,一個寫服務端應用的工程師,一個寫 Web 前端的工程師,以及對應的 Android 和 ios 工程師。
且不考慮系統(tǒng)本身的協(xié)作,要找到這么多的工程師就不是一件容易的事。而如果我們可以只使用一種語言,將大大地改善開發(fā)效率、開發(fā)人員的難題。JavaScript 語言下的物聯(lián)網(wǎng)架構
JavaScript 語言在最近幾年里特別流行,它流行起來有很多個原因,如:
- 使用 WebView 開發(fā) UI 效率更高,也因此使得 WebView 隨處可見;
- 基于事件驅動的編程模型;
- JavaScript 容易上手(這是優(yōu)點,也是缺點);
- 也因此,React、Unity 等框架提供了更多的可能性,可以讓開發(fā)者用 JavaScript 開發(fā)游戲、VR 應用等等。
那么,只使用 JavaScript,我們可以設計出怎樣的物聯(lián)網(wǎng)系統(tǒng)呢?
基于純 JavaScript 的物聯(lián)網(wǎng)架構
如上所述,幾年前要想尋找一門能完成一個包含客戶端、服務端的系統(tǒng)的語言可謂相當?shù)乩щy。而隨著客戶端(瀏覽器、移動設備)性能的提升、Node.js 的出現(xiàn),這樣的語言就浮現(xiàn)了出來,即 JavaScript。它不僅可以讓我們只用一門語言來降低開發(fā)成本,還能實現(xiàn)快速地開發(fā)出這樣的一個系統(tǒng)。那么,剩下的問題就是,在不同的層級,如何選用合適的框架來實現(xiàn)快速開發(fā)。
如圖 3 所示,我們可以看到不同層級的可選用 JavaScript 方案。在此之中,有些純粹只是為了證明 JavaScript 是可行的;有一些則可以在開發(fā)效率與運行速率上達到***的平衡。選用這些方案,可以讓我們實現(xiàn)更快速的 JavaScript 物聯(lián)網(wǎng)應用開發(fā)。
服務層
對于服務層來說,自主開發(fā)的物聯(lián)網(wǎng)服務端,主要采用的是基于 node.js 的方案。然而,我們發(fā)現(xiàn)有越來越多的應用,在使用 Serverless 的架構,不僅可以快速推出一個可用的原型,未來也能夠輕松地基于這個原型來添加業(yè)務功能。
圖 4 便是我們看到的物聯(lián)網(wǎng)服務層的三種方案:
- 自主開發(fā):即遵循傳統(tǒng)的服務端開發(fā)模式,定義自己所需要的功能;
- 使用云服務:直接使用成熟的物聯(lián)網(wǎng)云服務,它們在云端集成了各種所需要的功能;
- Serverless:Server 可以看作是在云服務之上的自主開發(fā),集兩者之便利。
每一種方案都有各自的特點,也適合于不同開發(fā)能力的項目。但如果要實現(xiàn)快速的開發(fā),那么理想的方式便是采用 Serverless 架構模式。
自主開發(fā)
出于不同的原因,諸如保密、安全、可擴展、核心技術等原因,一定規(guī)模的公司會采用自主開發(fā)的方式。這種開發(fā)方式與 Web 應用開發(fā)方式并沒有太大區(qū)別,都是在數(shù)據(jù)進行 CRUD 操作。并且和前后端分離架構一樣,使用 API 作為接口,同時再加上支持不同的傳輸協(xié)議,如 MQTT、CoAP 等。
如筆者之前在 GitHub 上開源的 Lan(https://github.com/phodal/lan),便是一個精簡的物聯(lián)網(wǎng)服務端示例。基于 Node.js 與 MongoDB,其架構如圖 5 所示。
- 采用傳統(tǒng)的關系型數(shù)據(jù)庫來存儲用戶信息;
- 采用 NoSQL 可以應對不同的傳感器數(shù)據(jù);
- 提供 UI 界面供管理人員管理用戶;
- 在協(xié)議上提供 HTTP、CoAP、MQTT、WebSocket 等的支持,方便不同的類型適配。
除此,物聯(lián)網(wǎng)系統(tǒng)在存儲上,采用 NoSQL 作為存儲介質會有更大的優(yōu)勢。一般來說,物聯(lián)網(wǎng)系統(tǒng)的數(shù)據(jù)都是寫入遠遠多于讀取的場景。與此同時,由于設備的種類繁多,不可能為每一類設備創(chuàng)建表;或者考慮到大量設備的特性,來建立一個通用的表,但在未來這樣的表可能仍不適用。
因此,對于物聯(lián)網(wǎng)數(shù)據(jù)來說,選用諸如 mongodb 這一類的 NoSQL 數(shù)據(jù)庫,有這么一些優(yōu)點:
- 靈活性。采用非結構化的數(shù)據(jù)模型,可以存儲和處理任何結構的數(shù)據(jù);
- 支持水平擴展。NoSQL 數(shù)據(jù)庫的分布式存儲架構,帶來了優(yōu)秀的水平擴展性;
- 實時數(shù)據(jù)分析。如 MongoDB 可以通過豐富的索引和查詢支持,包括二次、地理空間和文本搜索索引,聚合框架和本地 MapReduce,可以針對傳感器數(shù)據(jù)就地運行報告分析。
然而,這樣的系統(tǒng)不免存在研發(fā)周期長的問題。如果需要快速驗證,那么應該考慮使用云服務來完成部分功能。
物聯(lián)網(wǎng)云服務
對于硬件團隊來說,直接使用云服務是一種更簡單、快速的搭建物聯(lián)網(wǎng)系統(tǒng)的方法。而使用物聯(lián)網(wǎng)云服務,就意味著:我們可以直接上硬件層的傳感器數(shù)據(jù),并在應用層獲取、分析這些數(shù)據(jù)。這一類的服務,比較成熟的有 AWS IoT Things(如圖 6 所示)、Azure IoT 等。
基于 AWS IoT Things,我們只需要在云端,定義好對應的數(shù)據(jù)處理規(guī)則,便可以在硬件端直接對接服務。不過值得注意的是,單一的云服務無法提供復雜的功能,這個時候就需要一些搭配額外的服務。
Serverless
Serverless 架構(如圖 7 所示)是云服務的一種,但是它在可編程與云服務之間做了一個折中。它是一種基于互聯(lián)網(wǎng)的技術架構理念,應用邏輯并非全部在服務端實現(xiàn),而是采用 FaaS(Function as a Service)架構,通過功能組合來實現(xiàn)應用程序邏輯。
從理論上來講,這些服務提供的是一層 API 封裝,它不會限制我們所使用的語言。使用 Serverless 服務,我們可以具備更好的快速開發(fā)能力,并且能使用同一種語言(JavaScript)來完成編程。
在這個過程中,開發(fā)者要所做的便是:在不同的服務之間傳輸數(shù)據(jù),每一次都只處理下一個服務所需要的數(shù)據(jù),類似于 Pipe and Filters 架構模式。如一個典型的物聯(lián)網(wǎng)應用的數(shù)據(jù)傳輸過程中是這樣的:
- 對設備進行鑒權;
- 轉換、存儲設備的數(shù)據(jù);
- 廣播通知其他監(jiān)聽此設備數(shù)據(jù)的服務;
- 后臺查詢數(shù)據(jù);
- 分析數(shù)據(jù)(AI);
- 可視化數(shù)據(jù)。
只需要少量的編程,我們就可以完成服務端的開發(fā)。隨后,專注于硬件層的開發(fā),以及應用層的業(yè)務功能。
應用層
在應用層方面,已經(jīng)有大量的地方使用到了 JavaScript。除了傳統(tǒng)的桌面瀏覽器,還有更多的領域也可以用 JavaScript 來開發(fā)。比如移動應用,已經(jīng)有基于 Cordova + WebView 的成熟方案,還有近兩三年流行起來的 React Native,都可以讓開發(fā)者使用 JavaScript 完成物聯(lián)網(wǎng)移動應用的開發(fā)。又如微信小程序,可以直接用藍牙來連接硬件設備,也是使用 JavaScript 來編程。
因此,就目前的 Web 趨勢來看,在應用層,JavaScript 將是快速開始的主流選擇。
在日常中的應用中,我們可以發(fā)現(xiàn)物聯(lián)網(wǎng)的應用層,經(jīng)常作為協(xié)調裝置來連接硬件,并上傳應用的數(shù)據(jù)。諸如共享單車、智能手環(huán)應用等,它們既通過藍牙來獲取數(shù)據(jù),又上傳數(shù)據(jù)到服務端。與此同時,有相當多的應用是運行在桌面客戶端上的。故而在這一層級的應用,可謂是種類繁多。
今天,開發(fā)人員在做移動端的技術選型時,都會優(yōu)先考慮到跨平臺能力(android、iOS)。而在這些跨平臺框架里,混合應用框架 Cordova(WebView)和 react Native 是使用最為廣泛的兩個框架,且它們都是使用 JavaScript 作為核心開發(fā)語言。
Cordova 是使用 WebView 來渲染頁面的。因此與 Reavt Native 相比,使用 Cordova 的***優(yōu)勢是,可以復用已有的 Web 前端應用的邏輯,并且有大量的圖表工具可以直接使用——這一點在物聯(lián)網(wǎng)應用中特別重要。而在混合應用框架中,Ionic 是這個領域使用最多的 UI 框架。
React Native 使用原生組件來渲染 UI 組件,不僅可以解決 Cordova 飽受詬病的性能問題;同時,它還能嵌入 WebView,解決一些復雜的圖表顯示問題。
但是如果只能藍牙的交互,可以考慮 PWA 或微信小程序。運行在 Chrome 瀏覽器上的 PWA 應用,可以直接使用 Web Devices API,如 Bluetooth、NFC、USB,即在瀏覽器上直接調用原生接口,并實現(xiàn)對設備的控制。而諸如最近一年內流行的微信小程序,則也可以訪問藍牙、GPS、羅盤、加速度計等硬件接口,同時用戶不存在安裝成本,打開即用。
另外,諸如 Electron、NW.js 這樣的框架,可以讓開發(fā)者直接使用 WebView + Node.js 模塊開發(fā)物聯(lián)網(wǎng)桌面應用。它可以加速 UI 界面的開發(fā),并輕松地美化 UI 界面。
硬件層
在硬件層上,就當前而言,Arduino 是最合適的原型開發(fā)硬件,除此還有自帶 Wi-Fi 的 ESP8266 開發(fā)板。盡管使用 JavaScript 的開發(fā)板數(shù)量較少,也沒有 Arduino 這樣的成熟生態(tài),但是未來可期。在嵌入式領域,使用 JavaScript 編寫的代碼,具有移植性強、事件驅動、天生支持異步等特點。
令人遺憾的是,為了保持上面提到的那些 JavaScript 特性,當前的 JavaScript 開發(fā)板都需要處理性能比較高的處理器,這也導致了此類開發(fā)板在生產(chǎn)上存在較高的成本。不過,好在多數(shù)使用 JavaScript 作為開發(fā)語言的設備,都具有網(wǎng)絡功能連接到互聯(lián)網(wǎng),直接作為物聯(lián)網(wǎng)設備使用。
就目前而言,這一類的設備有 Tessel、Espruino、Ruff 等等,它們的處理器性能都相當不錯,價格也相對較高一些。但是,它們可以直接使用 JavaScript,能為軟件開發(fā)工程師屏蔽底層相關細節(jié),及事件驅動、異步特性,帶來更好的開發(fā)體驗。
幸運的是,Samsung 公司推出的開源物網(wǎng)框架 IoT.js,只需要 64KB RAM、200 KB ROM。在未來,或許它能解決一些制造成本上的問題。
協(xié)調層
當我們的硬件層不能直接聯(lián)網(wǎng)時,協(xié)調層就可以完成這樣的功能。作為一個協(xié)調層的設備,它應該能與一定數(shù)量的微控制器連接,接收它們的數(shù)據(jù),并上傳到服務端;又能與服務端通訊,獲取一些控制指令,并將這些指令準時地發(fā)送給不同的控制器。所以,它需要有更好的處理能力、更多的 RAM、ROM 等等。因此,在這一層級使用 JavaScript 便不存在成本問題。我們只需要使用和服務端、應用層相似的知識,就可以快速地連接設備到網(wǎng)絡中心。還能直接在本地的 Linux 機器上編寫代碼,并無縫地運行在設備上。
這一類應用,依賴于 Node.js 引擎來實現(xiàn)快速開發(fā)。它可以運行在帶有嵌入式系統(tǒng)的開發(fā)板上,如流行的 Raspberry Pi、OpenWRT 路由器等。
我們只需要一個運行嵌入式 linux 系統(tǒng)的開發(fā)板,就可以完成這樣的工作。與此同時,主流的 ARM 開發(fā)板都提供相應的 Linux 移植,因此在這個層級,我們也只需要關注于業(yè)務的實現(xiàn)。
小結
如上所述,物聯(lián)網(wǎng)應用的架構與 Web 應用的架構區(qū)別并不是太大,只是在這上面做一系列的演進。除了上面提到的一系列快速實踐框架,當前在 Web 開發(fā)中流行的一些開發(fā)思想,勢必也會引導到物聯(lián)網(wǎng)系統(tǒng)中:
- 微服務化;
- DevOps;
- 容器化。
物聯(lián)網(wǎng)會吸引互聯(lián)網(wǎng)的優(yōu)秀開發(fā)思想,并演進出更優(yōu)秀的架構。