摘要:微內核架構在大型前端系統中的應用只討論架構,不討論框架名詞解釋由一群盡可能將數量最小化的軟件程序組成,他們負責提供實現一個操作系統所需要的各種機制和功能。而微內核架構已經在操作系統和很多的產品的后端服務及前端中經過了很多的實踐。
微內核架構在大型前端系統中的應用
只討論架構,不討論框架1、名詞解釋
由一群盡可能將數量最小化的軟件程序組成,他們負責提供、實現一個操作系統所需要的各種機制和功能。這些最基礎的機制,包括了底層地址空間管理,線程管理,與進程間通訊。
2、設計理念將系統的實現,與系統的基本操作規則區分開來。它實現的方式是將核心功能模塊化,劃分成幾個獨立的進程,各自運行,這些進程被稱為服務。所有的服務進程,都運行在不同的地址空間。
讓服務各自獨立,可以減少系統之間的耦合度,易于實現與除錯,也可以增進可移植性。它可以避免單一組件失效,而造成整個系統崩潰,內核只需要重啟這個組件,不至于影響其他服務器的功能,使系統穩定度增加。同時業務功能可以視需要,抽換或新增某些服務進程,使功能更有彈性。
就代碼數量來看,一般來說,因為功能簡化,核心系統使用的代碼比集成式系統更少。更少的代碼意味更少的潛藏程序bug。
3、具體應用微內核架構在使用時主要考慮兩個方面『核心系統』和『插件模塊』。應用邏輯被劃分為獨立的『核心系統』和『插件模塊』,這樣就提供了良好的可擴展性與靈活性,應用的新特性和基礎業務邏輯也會被隔離。
一、核心系統核心系統通常是一個可以獨立運行的最小化模塊,操作系統(Windows NT、Mac OS X)就是這么實現的。從商業應用的角度來看,核心系統為那些特定的場景、規則、復雜的條件判斷提供了通用的業務邏輯,而插件模塊則提供了更為具體的業務邏輯。可以增加或擴展核心系統以達到產生附加的業務邏輯的能力。
二、插件模塊插件模塊通常是一個專業處理額外特性的獨立組件。通常,插件模塊之間是沒有依賴的,當然你也可以創建一個依賴其他插件模塊的插件,但不管怎么樣,讓插件模塊之間可以彼此通訊又不產生依賴是一個很重要的問題。
三、獲取插件模塊并判斷可用性核心系統需要知道每個插件的可用性并且知道如何獲取它們,一個通常的實現方式是使用一組注冊表。注冊表包括了每個插件的基本信息,包括名稱、數據規范、遠程訪問協議(取決于插件模塊如何和核心系統進行連接)以及其他自定義數據。比如百度網盤中用于上傳文件的上傳插件提供了插件名稱、數據規范(輸入、輸出數據)、數據格式(json、xml),如果這個插件是通過異步進行加載的,那么還會有一個具體遠程HTTP訪問協議地址。
四、連接到核心系統插件模塊可以通過多種方式連接到核心系統,包括OSGI(open service gateway initiative)、消息機制、web服務以及點對點的綁定(對象實例化,既依賴注入)。使用何種方式主要取決于具體的應用場景和特殊需求(單機部署、分布式部署),微內核架構默認沒有要求具體的實現方式,但是必須保證插件模塊之間不能產生任何依賴。
五、通信規范插件模塊和核心系統之間的通信規范分為標準規范和自定義規范,自定義規范通常是指某個插件模塊是由第三方服務開發的。這種情況下,就需要在自定義規范和標準規范之間提供一個Adapter,這樣核心系統就不需要關心每個插件模塊的具體實現。在設計標準規范之前制定一個版本策略很重要。
六、事件模式核心系統提供了多種事件模式,主要包括常用的點對點模式、發布訂閱模式。同時,事件的類型分為全局(系統級)事件、系統內部事件以及插件模塊內部事件。由于點對點模式中發送者和接收者之間沒有依賴關系并且一條消息只對應一個接收者,所以可以用作廣播全局(系統級)事件,比如調起某個插件模塊。而發布訂閱模式中訂閱者和發布者之間存在時間上的依賴性,可以用于系統內部事件和插件模塊的內部事件。此外,核心模塊也可以通過發布訂閱模式向外發布某些屬于業務基本操作規則的事件。
七、接口設計當插件模塊注冊到核心系統之后,通過系統級事件可以調起具體的某插件模塊。此時就需要核心模塊提供屬于基本操作規則的接口供插件模塊使用,同樣的,插件模塊也必須按照通信規范提供運行入口(類似于java的Main方法)和數據規范(參數格式,返回的數據格式),以此保障插件模塊可以在核心系統上正確運行。插件模塊是獨立于核心系統之外的,但是根據具體的需求(提供單純的數據服務、處理系統數據和信息)可能會需要操作核心模塊的系統服務做一些定制化功能,此時核心系統需要提供一個上下文對象(Context),且插件模塊與外部進行交互只能通過此上下文對象。上下文對象提供了基礎操作(調起其他插件模塊、調起系統服務、獲取系統信息)的API和事件。
4、在前端系統中使用把前端系統當成一個操作系統,業務基本操作的業務邏輯抽象成一個可以獨立運作的系統內核,而不屬于業務基本操作的業務邏輯都當成一個應用程序,完成安裝、卸載、禁用、調用以及開機啟動等功能。
在功能越來越多,依賴越來越負責的大型前端系統中,如果在項目初期沒有很好地考慮后期兼容的靈活性、擴展性以及彈性,很容易出現項目難以維護或者誰都不想碰的尷尬場面,所以初期的設計很重要。
目前的大型前端單頁面系統使用的都是根據業務劃分獨立組件,進行解耦和復用,最后通過組件進行堆疊、編譯、上線。這樣雖然完成依賴良好的組件化設計考慮到了系統的擴展性和靈活性以及彈性,但是整個系統還是緊緊綁在一起的,并沒有根據基礎業務和附加業務進行很好的拆分。當然很多優秀的前端工程師也考慮到了這一方面,提出來微前端的概念。不過微前端還是一個比較新的技術概念,沒有經過很多大型前端系統的實踐。而微內核架構已經在操作系統和很多的產品的后端服務及前端APP中經過了很多的實踐。
一、定義核心模塊和系統服務上面提到核心模塊是一個可以獨立運行起來,包含系統基本操作規則的最小化模塊。沒有任何插件模塊依然可以正常運行并處理基本的業務邏輯,所以在大型前端系統中將基礎頁面以及基礎功能多帶帶包裝起來,組成一個最小化的模塊,稱之為core system。而這個core system可以通過包方式在多個系統間進行復用(NPM、bower、bundle、js chunk)。同時,將那些和業務相關的操作按照類型和場景封裝為多個系統服務,并掛載(依賴注入)到核心系統中,稱之為system service。需要注意的是core system可操作system service,而system service不可操作core system。
此外,core system根據具體的模塊規范(AMD、CMD、CommonJS、ESM、SystemJS、UMD)向外部暴露了可交互的API和事件,稱之為標準接口。后續在編寫插件模塊時要嚴格按照標準接口進行開發。
二、定義插件模塊插件模塊是一個獨立于核心系統的專業處理不屬于系統基本操作的業務的模塊(組件),比如網盤中的上傳、下載、分享等功能。每個插件模塊必須遵照定義好的標準接口和通信規范進行開發,而且每個插件模塊都是相互獨立的,所以沒有對每個插件的實現細節做過多要求,如A插件模塊使用React開發,B插件模塊使用Vue開發,C模塊使用jQuery開發。
每個插件模塊都應該提供一個包含本插件模塊簽名信息(Mainfest)的JSON文件,簽名信息包括了這個插件的名稱、數據規范、依賴、遠程訪問地址(異步加載的js下載地址)和其他自定義字段。在前端加載核心系統時將該Mainfest文件注冊進去,完成核心系統和插件模塊的連接。
每個插件模塊都應該提供一個統一名稱的運行入口,比如start方法。也可以按照標準接口提供插件的生命周期事件,方便更細粒度的控制。
三、注冊和調起每個插件都提供了各自的Mainfest簽名文件和可執行文件(JS文件、CSS文件)。所以當服務器接收到瀏覽器請求時可以將所要求的插件Manifest進行merge,合并成一個大的JSON結構,然后返回給瀏覽器。瀏覽器接收后,執行核心系統并注冊Manfiest信息,然后啟動。在注冊過程中可以按照需求完成開機啟動(默認執行)、預加載以及后臺運行等不同類型的操作。
在業務邏輯和插件內部邏輯中可以能存在調起其他插件模塊的需求,由于插件模塊之間不產生依賴并且獨立于核心系統,所以無法直接進行調起。不過由于注冊表和點對點事件模式的存在,可以通過核心系統向外暴露的API傳入插件名稱和組、插件模塊ID等信息進行調起。在調起之前先判斷該插件在是否已注冊,是否已加載(同步加載、異步加載),是否為單例和互斥,參數信息和數據格式,保證它可以正確的調起。
在插件運行過程中出現異常時,通過系統級事件通知核心模塊。核心模塊根據簽名信息中的標識選擇重啟或關閉該插件模塊。
四、多入口管理在復雜的前端系統中同一個功能可能會存在過個入口的情況,比如上傳、下載、分享等功能都是通過不同位置的按鈕點擊進行調起。通常,將具體功能(插件模塊)和插件模塊入口的UI展示進行隔離。首先,在基礎頁面結構中按照需求進行分塊,分成不同的功能塊,如菜單欄、右鍵菜單、列表項、右側區域、左側區域,并為這些區域定義唯一的名稱和ID。在需要進行入口展示的插件模塊的Manifest中,標識入口的區域和展示方式(按鈕、圖片、引導塊、菜單項、下拉菜單)。
核心系統在注冊表注冊完畢后,解析那些需要展示入口的的字段并交給專門渲染插件模塊入口的系統服務,這樣就通過配置完成了多入口的管理,在后續需求變動和修改時,只需要更改Manifest文件即可,更加完善了系統的擴展性、靈活性、彈性。
5、技術選型架構是獨立于框架和類庫的存在。
微內核架構的核心就是使業務的基本操作和專業處理額外特性的操作相隔離,提高系統的擴展性、靈活性和彈性。所以在技術選型時我們需要考慮三個方面:核心系統、系統服務、插件模塊。
核心系統通常包含一個項目所需要的基本功能,包括基本的展示頁面、交互操作、業務處理,代碼量通常很少;系統服務提供業務處理的通用功能,比如列表操作、彈框、提示、異步化接口處理等,通常將系統中通用的需求抽象到這一層中;所以,這兩個方面可以使用目前常見的react或vue通過webpack工具進行規范化開發,但如何向外部暴露核心系統的API和事件給插件模塊調用是一個十分重要的問題。
插件模塊更傾向于一個專業處理額外特性的lib庫,所以推薦使用rollup或者webpack的lib模式進行開發和打包,產出一個『干凈』的bundle(也可以發布到NPM中,實現獨立發布和維護)。需要注意的是,如果這個bundle按照定義好的標準規范進行開發,那么它可以在任意一個微內核架構下運行,達到跨系統的能力。就像按照X86規范編寫的程序可以在任意一個X86架構的系統上運行一樣。
調起插件模塊時如何異步加載插件模塊bundle?方案一:source code
插件模塊的代碼放置在一個根文件夾中,通過源代碼進行開發和編譯。每次更改后通過rollup或webpack產出一個bundle與Manifest文件,然后將它們上線更新即可。
這種模式下,插件模塊的代碼更新后,對應的Manifest文件也會更新,所以核心系統加載到插件模塊也會被更新,不需要基礎業務邏輯執行任何操作。
優點:不需要更新并上線基礎業務代碼。
缺點:沒有版本號的管理功能以及不方便測試。
方案二:npm install
插件模塊發布到github、gitlab等其他托管平臺中,通過npm進行安裝到基礎業務邏輯中。插件模塊每次更改后需要重新發布到托管平臺,并在需要在業務邏輯中更新版本號重新執行npm install xxx,然后重新編譯業務代碼進行上線。
插件模塊更新后,不需要像方案一那樣上線插件模塊。而是更新業務邏輯的依賴,安裝最新版本的插件模塊。
優點:可以通過版本號加載不同的階段的插件模塊以及方便測試。
缺點:更改后需要重新安裝插件模塊,并對依賴此插件模塊的業務邏輯重新進行編譯和上線。回歸成本大,除了回歸插件模塊還要回歸其他基礎業務邏輯(當然也可以像方案一那樣做,但是這樣就拋棄了npm的最大優點 -> 版本號管理)。
方案一:服務器渲染直出到HTML中
服務器收到瀏覽器的頁面請求時,將該頁面需要的插件模塊的Manifest簽名文件進行Merge操作,然后統一輸出到HTML中并返回給瀏覽器。
方案二:通過異步化獲取
通過script標簽的async和defer功能或AJAX,異步從服務器獲取Merge之后的Manifest簽名信息集合。
核心系統調起插件模塊時,可以通過插件聲明的遠程訪問協議的HTTP地址,進行異步加載。
方案一:Manifest簽名文件
在Manifest簽名信息中放置插件模塊的遠程訪問協議,比如上傳插件模塊的簽名示例:
{ // 插件名稱 "name": "upload", // 組 "group": "com.xxx.xxx", // 預加載插件模塊資源 "preload": true, // 數據規范,要求輸入的參數 "arguments": { // 核心系統提供的上下文對象 "ctx": { "type": "Object", "required": true }, // 需要上傳的文件信息 "file": { "type": "Object", "required": false } }, // 遠程訪問協議 "entrance": "http://www.a.com/static/plugin-bundles/upload-0.0.1.min.js" }
方案二:異步化接口 + import()
該方案是系統插件模塊的遠程訪問協議不放置在插件模塊的Manifest中,而是額外通過異步化接口請求得到遠程訪問協議。然后通過webpack提供的require.ensure()或esm的import()加載插件資源。
// ctx為核心系統上下文對象 ctx.loadPlugInAdapter = (pluginName, group) => { // 通過接口請求上傳插件模塊的遠程訪問協議 fetchEntrance(pluginName, group).then(url => { // 核心系統執行插件模塊 ctx.invoke(pluginName, url); }); } // 調起插件模塊 ctx.loadPlugInAdapter("upload", "com.xxx.xxx");最后
架構和框架是獨立的,本文僅僅是提出一種架構思路,而且這個架構也在百度的某款用戶量很大的復雜前端產品中得以應用。基于這一套彈性架構并結合Vue/React的現代化開發理念,可以很好的完成高復雜度的前端系統。希望本文可以給你們提供了除微前端之外的構建高彈性前端系統的另外一種思路。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/11934.html
摘要:巨杉數據庫,作為新一代分布式數據庫,為多家大型金融客戶的云化架構升級提供了極為重要的助力。目前巨杉數據庫已在超過家強級別的大型商業銀行核心生產業務上線,企業用戶總數超過家。 作為一款金融級分布式關系型數據庫,SequoiaDB巨杉數據庫的分布式數據庫架構和面向微服務的云化產品形態,已經幫助包括民生銀行、恒豐銀行在內的多家大型金融客戶實現了大量業務系統的底層數據庫云化轉型升級。 如今,大...
閱讀 3228·2021-11-15 11:37
閱讀 2449·2021-09-29 09:48
閱讀 3812·2021-09-22 15:55
閱讀 3013·2021-09-22 10:02
閱讀 2635·2021-08-25 09:40
閱讀 3224·2021-08-03 14:03
閱讀 1691·2019-08-29 13:11
閱讀 1569·2019-08-29 12:49