基于JavaScript語言的快速物聯網開發架構
隨 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;
- 容器化。
物聯網會吸引互聯網的優秀開發思想,并演進出更優秀的架構。