如何將微服務(wù)體系結(jié)構(gòu)運(yùn)用于嵌入式系統(tǒng)?
譯文譯者 | 布加迪
審校 | 重樓
微服務(wù)體系結(jié)構(gòu)是Facebook、Netflix和優(yōu)步等跨國企業(yè)發(fā)布的分布式應(yīng)用系統(tǒng)的基礎(chǔ)。精細(xì)化隔離服務(wù),然后將它們聚合起來協(xié)同工作,這使得分布式系統(tǒng)比單體式系統(tǒng)更易于管理。但是對于嵌入式系統(tǒng)而言,情況就有點(diǎn)不同了。
不像在數(shù)據(jù)中心內(nèi)和跨數(shù)據(jù)中心運(yùn)行的面向微服務(wù)的體系結(jié)構(gòu)(MOA),嵌入式系統(tǒng)往往在硬件和用例方面是專用的——比如運(yùn)行在工業(yè)裝配廠中操作的一群機(jī)器人工人或控制自動(dòng)駕駛汽車。
面向微服務(wù)的體系結(jié)構(gòu)可以運(yùn)用于這些類型的環(huán)境,但是需要特別注意出現(xiàn)問題時(shí),您不能僅僅啟動(dòng)另一個(gè)容器來替換失效的容器。要做的工作不止這些。
為嵌入式系統(tǒng)編寫面向微服務(wù)的體系結(jié)構(gòu)需要一種不同的設(shè)計(jì)和實(shí)施方法。
面向微服務(wù)的體系結(jié)構(gòu)簡介
在深入討論將MOA運(yùn)用于嵌入式系統(tǒng)的細(xì)節(jié)之前,不妨先大致了解這種體系結(jié)構(gòu)的基本要素。
面向微服務(wù)的體系結(jié)構(gòu)旨在將應(yīng)用程序的行為分解為一群獨(dú)立存在但一致行動(dòng)的離散服務(wù)。MOA的工作方式是將離散服務(wù)分發(fā)到眾多遠(yuǎn)程位置。
通常,這些服務(wù)使用一種眾所周知的傳輸協(xié)議(比如TCP、UDP或HTTP)發(fā)送和接收數(shù)據(jù)。某種類型的組織、前端客戶端機(jī)制(比如在桌面或移動(dòng)設(shè)備上運(yùn)行的網(wǎng)頁或原生代碼)將各種服務(wù)聚集在一起,形成整個(gè)應(yīng)用程序的統(tǒng)一表示。然而如前所述,組成MOA的每個(gè)服務(wù)都是遠(yuǎn)程托管的。
應(yīng)用程序的前端調(diào)用遠(yuǎn)程路由/控制器服務(wù)。路由/控制器服務(wù)知道組成應(yīng)用程序的微服務(wù)的位置,并根據(jù)作為調(diào)用代碼一部分的某種標(biāo)識符將調(diào)用轉(zhuǎn)發(fā)到適當(dāng)?shù)姆?wù)。微服務(wù)處理調(diào)用,并將結(jié)果發(fā)回給路由器/控制器作進(jìn)一步處理——或者如果某個(gè)調(diào)用完成,則將響應(yīng)發(fā)回給調(diào)用客戶端。
圖1. 面向微服務(wù)的體系結(jié)構(gòu)的基本模式
將應(yīng)用程序分成托管在遠(yuǎn)程位置的功能這個(gè)想法始于遠(yuǎn)程過程調(diào)用(RPC)。MOA通過添加一組常規(guī)需求來增強(qiáng)RPC模式。在MOA下,每個(gè)微服務(wù):
- 支持單個(gè)關(guān)注點(diǎn)
- 是離散的
- 承載自己的數(shù)據(jù)
- 可以傳輸
- 是短暫的
以下是這每一項(xiàng)要求的含義:
支持單個(gè)關(guān)注點(diǎn)
微服務(wù)應(yīng)該將其行為限制在單個(gè)關(guān)注點(diǎn)上,比如登錄服務(wù)、訂購服務(wù)、購買、處理信用卡交易的服務(wù)、支持客戶配置文件的服務(wù)、執(zhí)行稅收計(jì)算的服務(wù)或日志記錄服務(wù)。
一個(gè)微服務(wù)可以使用另一個(gè)微服務(wù),比如采購服務(wù)可以使用稅收計(jì)算服務(wù)來確定訂單的總金額。然而,不應(yīng)該將兩個(gè)服務(wù)組合到一個(gè)代碼庫或單個(gè)部署單元中。
是離散的
微服務(wù)應(yīng)該是離散的,因?yàn)樗鼞?yīng)該被限制在單個(gè)部署單元中,并在網(wǎng)絡(luò)上有清晰的邊界。該部署單元可能是Linux容器,也可能是代碼工件,比如Java .jar文件、.NET DLL或Rust二進(jìn)制文件。以嵌入式系統(tǒng)為例,部署單元可能是一個(gè)實(shí)際的硬件。
微服務(wù)的內(nèi)部組件應(yīng)該是私有的,公眾無法訪問。然而,公共訪問應(yīng)該由定義良好的API提供。
承載自己的數(shù)據(jù)
微服務(wù)承載自己的數(shù)據(jù),除了通過API外,不與另一微服務(wù)共享數(shù)據(jù)。通常,微服務(wù)會有自己的數(shù)據(jù)庫或數(shù)據(jù)庫中隔離良好的表。雖然微服務(wù)之間可能出現(xiàn)數(shù)據(jù)冗余,但這種情形是可以接受的,也是微服務(wù)維護(hù)自己的操作狀態(tài)和邊界所必需的。
可以傳輸
微服務(wù)必須能夠在任何時(shí)候傳輸?shù)饺魏瓮泄墉h(huán)境。當(dāng)微服務(wù)在一臺發(fā)生故障(比如斷電)的機(jī)器上運(yùn)行,又必須重新部署到另一臺正常運(yùn)行的機(jī)器上時(shí),可傳輸性非常重要。
是短暫的
微服務(wù)必須能夠按需創(chuàng)建或銷毀。在微服務(wù)執(zhí)行高強(qiáng)度計(jì)算、只需要滿足暫時(shí)需求的情況下,這一點(diǎn)尤為重要。比如說,微服務(wù)對特定的視頻文件執(zhí)行特效處理。
面向嵌入式設(shè)備的MOA有何特別之處?
與為數(shù)據(jù)中心應(yīng)用程序編寫MOA相比,為嵌入式環(huán)境實(shí)施MOA需要不同的方法。
首先,大多數(shù)數(shù)據(jù)中心使用Linux操作系統(tǒng)來驅(qū)動(dòng)機(jī)器。Linux是一個(gè)功能齊全的操作系統(tǒng),占用大量的內(nèi)存和磁盤空間。即使是Alpine之類精簡版的Linux發(fā)行版(只有一些基本功能),這個(gè)操作系統(tǒng)也占用5MB的存儲空間。
許多嵌入式芯片(比如EPS32)搭載大約520KB的內(nèi)部內(nèi)存,其中一些容量專用于非易失性存儲。使用特殊配置時(shí),一些芯片可能擁有高達(dá)4MB的內(nèi)存和2MB到16MB的閃存。
不過,當(dāng)嵌入式設(shè)備的存儲量有限(小于4MB)時(shí),Linux無法工作。相反,嵌入式設(shè)備通常使用某種版本的實(shí)時(shí)操作系統(tǒng)(RTOS)。ESP32芯片組上使用的FreeRTOS操作系統(tǒng)只需要5 KB到10KB的代碼存儲,內(nèi)存使用低至300 KB。正如您所見,與數(shù)據(jù)中心中運(yùn)行的機(jī)器相比,嵌入式設(shè)備的系統(tǒng)需求非常小。
此外,雖然Linux支持容器,允許多個(gè)微服務(wù)在虛擬機(jī)集群中運(yùn)行,但在嵌入式系統(tǒng)中,容器支持更多的是一種例外,而不是常態(tài)。通常,微服務(wù)將在專用的嵌入式微處理器上運(yùn)行。微服務(wù)和運(yùn)行微服務(wù)的硬件之間的一對一關(guān)系影響了部署和升級微服務(wù)的方式。
這不是使用Kubernetes之類的容器管理框架來重新部署容器的問題。相反,要進(jìn)行升級,需要直接連接到嵌入式處理器,并且在許多情況下需要停用作為升級目標(biāo)的設(shè)備。
比如說,升級運(yùn)行汽車制動(dòng)系統(tǒng)的微服務(wù)需要汽車沒有在路上行駛、處于靜止?fàn)顟B(tài)。
簡而言之,為嵌入式系統(tǒng)部署和升級微服務(wù)的過程高度依賴系統(tǒng)硬件的物理狀態(tài),但是還有另一個(gè)重要的限制因素:數(shù)據(jù)交換。
嵌入式設(shè)備之間的數(shù)據(jù)交換最好使用二進(jìn)制數(shù)據(jù)格式來實(shí)施。嵌入式處理器中的空間和帶寬容量有限,因此基于文本的格式(比如XML和JSON)不能很好地工作。
相反,像協(xié)議緩沖區(qū)這樣的二進(jìn)制格式或自定義二進(jìn)制格式更適合MOA場景中的通信,在這種場景中,體系結(jié)構(gòu)中的每個(gè)微服務(wù)都托管在嵌入式處理器上。
然而,本身在特定設(shè)備(比如汽車)內(nèi)運(yùn)行的嵌入式處理器和外部設(shè)備(比如手機(jī))之間進(jìn)行數(shù)據(jù)交換需要特別考慮。大多數(shù)嵌入式處理器在小型迷你板上搭載其他芯片,如圖2所示。
圖2. ESP32迷你板支持藍(lán)牙和Wi-Fi通信
這些迷你板內(nèi)置藍(lán)牙和Wi-Fi功能。嵌入式芯片組可以使用這些功能與板外設(shè)備進(jìn)行通信。在嵌入式芯片組根據(jù)已知格式與已知外部設(shè)備通信的情況下,使用二進(jìn)制格式進(jìn)行通信仍然是切實(shí)可行的。
在某些情況下,比如使用HTTP與遠(yuǎn)程Web API通信時(shí),較笨拙的基于文本的數(shù)據(jù)格式是規(guī)定的數(shù)據(jù)交換方式??紤]到芯片在存儲和內(nèi)存方面的限制,讓每個(gè)嵌入式芯片組參與基于文本的通信可能是個(gè)問題。
另一種方法是使用專用代理芯片組與外部設(shè)備進(jìn)行通信,該芯片組支持HTTP,并擁有增強(qiáng)的存儲和內(nèi)存功能。專用代理負(fù)責(zé)管理來自其他板載嵌入式處理器的外部目標(biāo)的通信。(參見圖3。)
圖3. 外部目標(biāo)的專用代理使嵌入式芯片組能夠有效地通信
服務(wù)路由是另一個(gè)需要考慮的問題。正如數(shù)據(jù)中心中運(yùn)行的MOA需要API網(wǎng)關(guān)將流量路由到指定的微服務(wù)一樣,嵌入式環(huán)境中運(yùn)行的MOA也需要這樣的路由器/控制器機(jī)制。在一輛汽車中,路由器/控制器是在汽車控制器局域網(wǎng)(CAN)上運(yùn)行的電子控制單元(ECU)。(參見圖4。)
圖4. 汽車中的CAN使用電子控制單元(ECU)來協(xié)調(diào)嵌入式設(shè)備上運(yùn)行的微服務(wù)之間的數(shù)據(jù)交換
ECU可以感知汽車內(nèi)運(yùn)行的所有組件,并據(jù)此制定路由路線。此外,ECU還可以是維護(hù)全局狀態(tài)的控制點(diǎn)。
許多傳統(tǒng)的分布式應(yīng)用程序可以在不需要應(yīng)用程序中的每個(gè)微服務(wù)立即了解應(yīng)用程序整體狀態(tài)的情況下運(yùn)行。然而,了解系統(tǒng)的整體狀態(tài)對于在嵌入式系統(tǒng)中運(yùn)行的微服務(wù)非常重要。
比如說,當(dāng)自動(dòng)駕駛汽車中的傳感器看到道路上的障礙物時(shí),制動(dòng)系統(tǒng)需要知道車輛處于危險(xiǎn)的全局狀態(tài),以便做出相應(yīng)的反應(yīng),因此需要普遍感知全局狀態(tài)。
飛行控制系統(tǒng)(FCS)和樓宇管理系統(tǒng)(BMS)也有維護(hù)和報(bào)告全局狀態(tài)的機(jī)制。在FCS中,控制機(jī)制名為飛行管理系統(tǒng)或飛行管理計(jì)算機(jī)。
在BMS中,該組件名為樓宇自動(dòng)化控制器或樓宇自動(dòng)化系統(tǒng)控制器。樓宇自動(dòng)化控制器報(bào)告樓宇中所有子系統(tǒng)的狀態(tài),比如暖通空調(diào)、照明、安全、電梯、電氣系統(tǒng)和消防安全設(shè)備。
需要理解的重要一點(diǎn)是,任何嵌入式系統(tǒng)都需要一種路由機(jī)制來協(xié)調(diào)組成系統(tǒng)的各種設(shè)備之間的流量和數(shù)據(jù)交換。
把它們組合起來
從智能家居、自動(dòng)駕駛汽車到機(jī)器人運(yùn)行的工廠,物聯(lián)網(wǎng)和智能設(shè)備呈爆炸式增長,為精通面向微服務(wù)體系結(jié)構(gòu)的軟件開發(fā)人員提供了處理嵌入式系統(tǒng)的更多機(jī)會。
將面向微服務(wù)的體系結(jié)構(gòu)運(yùn)用于嵌入式系統(tǒng)需要一些新知識,還需要與用于創(chuàng)建在數(shù)據(jù)中心虛擬化環(huán)境中運(yùn)行的業(yè)務(wù)應(yīng)用程序的平常做法略有不同的軟件開發(fā)方法。但考慮到面臨的機(jī)會,有望獲得重大的投資回報(bào),值得我們應(yīng)對這一挑戰(zhàn)。
原文標(biāo)題:How to Apply Microservice Architecture to Embedded Systems,作者:Bob Reselman