什麼是微內核架構設計?

簡介: 做爲一名Java程序員,相信同窗們都據說過微內核架構設計,也有本身的理解。那麼微內核是如何被提出來的?微內核在操做系統內核的設計中又有什麼做用?本文從插件化(Plug-in)架構的角度來詮釋微內核架構設計,經過微內核架構和微服務架構的對比,分享其對微服務設計的參考意義。

關於微內核架構設計如今比較熱,聽起來好像是操做系統內核相關的,做爲Java程序員,操做系統內核那麼遙遠的事情,好像和咱們沒有什麼關係。可是若是我說微內核其實就是插件化(Plug-in)架構,你必定會一臉疑惑,「你竟然向Java程序員解釋什麼是插件化架構?我天天都在用啊,Eclipse、IntelliJ IDEA、OSGi、Spring Plugin、SPI等,哪一個不是插件化架構。個人一些項目也是採用插件化設計的,如使用插件實現流程控制定製等等」。可是彆着急,即使是咱們天天都在使用的技術,並且大多數人也都知道,若是咱們能將其闡述得更清楚,而且能從中發現一些問題,作出一些優化有助於之後的架構設計,那麼大多數人在平常的設計和開發中都能受益,豈不是更好。如今咱們就來聊一聊微內核架構設計。git

1、 微內核設計之操做系統內核

微內核設計其實就是插件體系。咱們都知道,操做系統內核誕生得比較早,因此插件化最先被用在內核設計上,因而就有了微內核設計這一稱呼。程序員

微內核是這樣一種內核:它只完成內核不得不完成的功能,包括時鐘中斷、進程建立與銷燬、進程調度、進程間通訊,而其餘的諸如文件系統、內存管理、設備驅動等都被做爲系統進程放到了用戶態空間。說白了,微內核是相對於宏內核而言的,像Linux就是典型的宏內核,它除了時鐘中斷、進程建立與銷燬、進程調度、進程間通訊外,其餘的文件系統、內存管理、輸入輸出、設備驅動管理都須要內核完成。github

也就是說,微內核是相對宏內核而言的,宏內核是一個包含很是多功能的底層程序,也就是咱們如今講的Monolith。它乾的事情很是多,並且不是可插拔的,修改一些小的功能,都會涉及到整個程序的從新編譯等,好比一個功能出現了一個小bug,可能致使整個內核都出問題。這也是不少人將Linux稱爲monolithic OS的緣由。而微內核只負責最核心的功能,其餘功能都是經過用戶態獨立進程以插件方式加入進來,而後微內核負責進程的管理、調度和進程之間通信,從而完成整個內核須要的功能。基本一個功能出現問題,可是該功能是以獨立進程方式存在的,不會對其餘進程有什麼影響從而致使內核不可用,最多就是內核某一功能如今不可用而已。數據庫

微內核就是一個運行在最高級別的程序片斷,它能完成用戶態程序不能完成的一些功能。微內核經過進程間通訊來協調各個系統進程間的合做,這就須要系統調用,而系統調用須要切換堆棧以及保護進程現場,比較耗費時間;而宏內核則是經過簡單的函數調用來完成各個模塊之間的合做,因此理論上宏內核效率要比微內核高。這個和微服務的架構設計同樣,咱們將Monolith應用劃分爲多個小應用後,系統的設計就變得比較複雜了,以前都是應用內部函數調用,如今要涉及網絡通信、超時等問題,同時響應時間會被拉長。服務器

聊到這裏,相信你們對微內核和宏內核已經有了一個大體的瞭解,看起來各有千秋。可是宏內核有一個最大的問題就是定製和維護陳本。如今的移動設備和IoT設備愈來愈多,若是要把一個龐大複雜的內核適配到某一設備上,是一件很是複雜的事情,若是很簡單的話,那麼把Linux內核適配到Android內核,甚至到Tesla等車載系統,基本上人人均可以作了。網絡

所以咱們更須要一個微內核的架構設計,方便定製,並且很是小,能夠實現功能的熱替換或者在線更新等,這就是微內核被提出來的核心需求。可是微內核有一個運行的效率問題,因此在微內核和宏內核之間,又有了Hybrid內核,主要是想擁有微內核的靈活性,同時在關鍵點上有宏內核的性能。微內核設計在理論上確實有效率問題,可是隨着芯片設計、硬件性能提高等,這方面或許已經有了很是大的提高,已經再也不是最關鍵的問題。架構

整體下來,內核設計有三個形式,以下:異步

2、 插件化(Plug-in)架構設計

上面聊了微內核在操做系統內核設計中的做用,接下來咱們就開始討論更通用的插件化架構設計,畢竟這個詞你們都明白。分佈式

插件化架構很是簡單,就兩個核心組件:系統核心(Core System)和插件化組件(Plug-in component)。Core System負責管理各類插件,固然Core System也會包含一些重要功能,如插件註冊管理、插件生命週期管理、插件之間的通信、插件動態替換等。總體結構以下:ide

插件化架構對微服務架構設計幫助很是大,考慮到隔離性,插件多是以獨立進程方式運行的,那麼這些進程若是擴展到網絡上,分佈在衆多的服務器上,這個就是微服務架構的原型,因此瞭解微內核的同窗都不屑於和你討論微服務架構,相信你也明白了,除了IT傳統的鄙視鏈因素,原理上確實就是這麼回事。

回到微服務架構設計場景,咱們將Plug-in component從新命名爲服務(Service),這個和微內核設計中的服務也差很少,這個時候微服務和微內核就差很少了,都涉及到服務註冊、管理和服務之間的通信等。那咱們看一下微內核是如何解決服務之間的通信問題的?如下摘自維基百科:

由於全部服務行程都各自在不一樣地址空間運行,所以在微核心架構下,不能像宏內核同樣直接進行函數調用。在微核心架構下,要建立一個進程間通訊機制,經過消息傳遞的機制來讓服務進程間相互交換消息,調用彼此的服務,以及完成同步。採用主從式架構,使得它在分佈式系統中有特別的優點,由於遠程系統與本地進程間,能夠採用同一套進程間通訊機制。

也就是說,採起的是基於消息的進程間通信機制。消息最簡單,就兩個接口:send和receive,消息發送出去,而後等着收消息,處理後再發消息就能夠了,這裏你們應該也知道了,這個是異步的。回到插件化架構設計中,Plug-in組件設計包含交互規範,也就是和外界相互通信的接口,若是是基於消息通信的話,就是send和receive接口,能夠說是很是簡單的。

可是這裏還有一個問題,那就是進程間通信。你可能會問,這個有什麼好疑問的,就是兩個進程之間相互發消息唄。可是這裏有一個最大的疑問,那就是進程間通信是否有第三者介入?以下圖:

固然在操做系統的內核設計中,必定是經過內核進行轉發的,就是咱們理解的總線架構,內核負責協調各個進程間的通信。這個你們也能理解,若是進程A直接發給另一個進程B,必然要了解對應的內存地址,微內核中的服務是能夠被隨時替換的,若是服務不可用或者被替換,這個時候要通知和其通信的其餘進程,是否是太複雜?剛纔已經提到,只有send和receive接口,沒有其餘通知下線、服務不可用的接口。在微內核的設計中,必定是經過總線結構,進程向Kernel發送消息,而後kernel再發送給對應的進程,這樣的一個總線設計。實際上不少應用內部在作Plug-in組件解耦時,都會使用EventBus的結構,其實就是總線的設計機制。

爲什麼婆婆媽媽說這些?由於很是關鍵。分佈式的進程通信是微服務的核心,咱們理解的服務到服務的通信,就是服務A啓動監聽端口,服務B會和服務A創建鏈接,而後二者通信便可。這個方式和微內核設計中內核負責消息接收和轉發的總線架構設計是不同的。如採用HTTP,HSF等通信協議時,至關於kernel告知通信的雙方各自的地址,而後它們之間就能夠通信了。而後就沒有Kernel什麼事情了,也不會用到什麼總線的結構設計,這個就是傳統的服務發現機制。

可是還有一種模式,就是徹底透明的插件化通信機制,以下圖:

Plug-in組件,也就是微服務架構中的服務,是不能直接通信的,而是須要Core System進行轉發。這樣作的好處和微內核架構同樣,插件相互之間無直接聯繫,彼此之間很是透明,例如服務A下線後,徹底不須要通知其餘服務;服務A被替換,也不須要通知其餘服務;服務A從數據中心1到數據中心2,也不用通知其餘服務;即使服務N和服務A之間網絡不互通,二者之間也能通信。

這裏有個問題:性能問題。咱們都知道,兩點之間,直線段最短。爲什麼要多繞一下到Core System呢?這就是微內核和宏內核之間的爭論之處,使用函數調用很是快,而進程間的消息通信則是很是慢的,可是這種經過中介進行通信機制的好處也是很是明顯的。那麼如何提高這種基於總線的通信性能呢?固然有,好比選擇高性能的二進制協議,HTTP 1.1這種文本協議就不須要了;採用Zero Copy機制,能夠快速進行網絡包轉發;好的網絡硬件,如RDMA;好的協議,如基於UDP的QUIC等。總結下來,和微內核同樣,這種微服務通信的性能是能夠提高的。固然若是實在受不了這種性能,在關鍵場景,你能夠採用Hybrid模式,混入一些服務之間直接通信的設計,但只能在性能極致的場景中使用。

此外,插件化架構中的插件組件是各類各樣的,通信的機制也各不同,一些是RPC的,一些是Pub/Sub的,一些是無需ACK的(如Beacon接口),還有一些是雙向通信的等等。固然你能夠選擇不一樣的通信協議,可是這裏有一個問題,就是Core System須要理解這個協議,而後才能進行消息路由。這個時候Core System須要編寫大量的Adapter來解析這些協議,例如Envoy包含各類filter來支持不一樣的協議,如HTTP、MySQL、ZooKeeper等,可是所以Core System就會變得很是複雜且不穩定。

另外能夠選一種通用的協議,Core System只支持這一種協議,各個插件之間都基於該協議通信,至於服務和其餘外部系統如何通信,如數據庫、github集成等,這些Core System並不關心,那只是Service內部的事情。目前比較通用的協議是gRPC,如K8s內部都會採用該協議,另外Dapr也採用gRPC協議作服務集成,由於gRPC提供的通信模型基本能夠知足大多數的通信場景。固然另一個就是RSocket,提供更豐富的通信模型,也適用於Core System這種服務間通信場景。對比gRPC,RSocket能夠運行在各類傳輸層上,如TCP、UDP、WebSocket、RDMA等,相反的,gRPC目前只能運行在HTTP 2之上。

3、 服務通信的延伸

前面說到,最好由插件化架構設計的Core System做爲服務之間消息通信的路由,若是是這樣的話,就會產生一種Broker模式,固然也有多是Agent。這裏你們必定會想到Service Mesh,沒錯。固然你能夠選擇Agent Sidecar模式,也能夠選擇中心化的Broker模式,這二者的功能都是同樣的,只是處理的方式不同而已。Agent基於服務註冊和發現機制,而後找到對方服務的Agent,再進行兩個Agent之間的通信,只是省掉服務之間的調用的開銷。可是Broker是集中式的,你們都向Broker發送和接收消息,不涉及服務註冊發現機制,不涉及服務元信息推送,就是總線結構。

我如今作的就是基於這種Broker的總線的架構設計,在RSocket Broker中,也是採用微內核架構設計,固然未必作得最好 。RSocket Broker核心就是管理註冊的服務、路由管理、數據採集等,而不會添加過多的功能,和Core System的設計理念同樣,只添加必須的功能。若是你要擴展整個系統更多的功能,如發短信、發郵件、對接雲存儲服務等,須要編寫一個Service ,而後和Broker對接一下,再從broker那裏收消息(receive),處理完畢後再發送(send)給Broker就能夠了。整體結構以下:

有很多同窗會問,當服務實例的負載過高的時候,Broker如何實現動態擴容呢?Broker會給你提供數據,如一個服務實例QPS,至因而否擴展,你只須要寫一個服務,從Broker上採集數據,分析後,調用K8s API進行擴容便可,Broker並不負載這些業務功能,它只會添加很是必要的功能,這個和Core System設計是同樣的。

回到插件化架構的靈活性上,若是系統中有一個KV存儲的插件,你只要遵循消息格式或者通信接口,就能夠保存KV數據。可是你並不太關心是Redis存儲的,仍是Tair存儲的,或者是雲端的KV服務,這就爲服務標準化和可替換性提供了很好的基礎,這對應用上雲或雲原生化幫助很是大,整個系統有很是大的靈活性。

四 、總結

其實有很是多的書有關於微內核的介紹,操做系統的圖書就不用說了,另外兩本書也很是不錯,對通用架構設計幫助也很是大,尤爲是微服務的場景,我也是參考這兩本書寫這篇文章的。

微內核架構設計對微服務設計有很是好的參考意義,可是微服務有一個很是大的問題就是服務邊界的劃分,對比操做系統,已經發展幾十年,並且很是穩定,功能劃分很是容易。而微服務架構是爲業務服務的,雖然面對的業務可能已經存在上百年,可是軟件化、數字化和流程化並無多少年,加上現實業務的複雜性,還有各類妥協,我的認爲微服務架構會更復雜一些。

做者:開發者小助手_LS
原文連接本文爲阿里雲原創內容,未經容許不得轉載

相關文章
相關標籤/搜索