一個微服務框架的細節
KingWorks微服務系列文章:
(一)一個微服務框架的故事
(二)一個微服務框架的情節
從KingWorks-0.0.0版本(想象版本)開始,我就知道我踏上了一條“不歸的自主研發路線”,到目前的KingWorks-3.0.0,我始終堅守著這一份執著。曾經想過放棄,因為它不是“開源主流”;曾經想過放棄,因為它很費力;曾經想過放棄,因為為了讓它生命力不斷,我需要付出的精力比專研幾個新框架還要累得累。我堅守了,是因為它的簡單;我堅守了,是因為同事們的喜歡;我堅守了,是因為它讓我的心血在許多一線系統中滾滾流動。
微服務初心
我們微服務是為了把“大事化小小事化無”,但問題往往是從“小事作大”,如果我們以“微服務”理念從事小捉起,雖不可避免未來不確定性,但至少可以抵禦歷史風險。從過去經驗可以知道,一個系統的成長基本要經歷“單體-集群-分布式”的發展模式,前提是你開發的系統生命力足夠強大。我們都知道,“微服務”是一種分布式架構,一個小小的應用系統直接“分布式”感覺未免有點“關公刀削蘋果”,但如何避免一百個“小生命”當中有那麽其中一兩個可以粗壯成長所帶來的痛楚呢?也就是說,如何用一個“微服務”理念的架構更簡單、便捷與高效地去孵化一個個從0到N的關鍵機會。如果一個系統的每一個發展階段都需要大動幹戈,除了資金成本外,最重要的還是時間成本,綜合來說,這都是試錯成本。這已經不是一個“如何把一個大問題解決”的問題,而是一個“如何解決由一個小問題發展到大問題等一些列問題”的問題。我相信沒有天生的大問題,每一個創(chuang)新(ye)都是一個從小到大的試錯過程,如何把試錯成本降到最低,是我最為關心的問題,因為機會是留個有準備的人。
微服務容器
最簡單、便捷以及高效的理想狀態就是系統發展過程的一個“趨0變動”。也就是系統從“單體”到“集群”,再從“集群”到“微服務”的發展過程中無須改動(過多)代碼即可簡單達到各種支撐模式的切換。為了達到這種效果,我想到了“容器”的概念。例如Docker容器或JVM容器,它們提供的只是“單元”運行的環境,輕松聚合和分離單例的運行。從“微服務”理念看,“服務”作為我們業務的“執行單元”,同樣可以存在一個微服務應用容器,給個“服務單元”提供輕量級的運行環境,從而達到輕松聚合和分離服務的可能性。
KingWorks-MSAC(微服務應用容器,以下簡稱“微容器”)是我們KingWorks微服務框架的核心組件,它主要有六大功能特點,分別是映射、驅動、代理、管控、管理以及適配。
映射:按照規則可以根據URI訪問路徑信息分發到指定的服務處理當中;
驅動:激活每個框架約定下的服務線程執行單元;
代理:代理執行應用六大生命周期模塊組件,如初始化模塊組件、銷毀模塊組件、業務前置模塊組件、業務邏輯模塊組件、業務後置模塊組件以及定時器模塊組件;
管控:對服務生命周期內的狀態進行統一管控,如服務註冊、服務註銷、服務發現、服務心跳、服務訪問限制、服務並發限制以及遠程配置同步等狀態行為;
管理:對服務信息的統一管理,如服務單元信息、統一配置信息、服務列表信息以及各種服務狀態信息;
適配器:服務與“外界”聯系的中間件統稱“適配器”,如數據量連接組件、Redis連接組件、遠程訪問。
(微)服務結構
以上單元服務工程的構建目錄結構主要是基於KingWorks微服務框架的高約束和高標準的體現,具體說明如下:
服務目錄:一個服務的身份和標準定義(com.kingworks.xxxsop/smp),其中xxx為服務標識,如以上例子,test就是本演示服務的標識,smp/sop為服務類型,smp代表面向信息管理服務、sop代表面向業務支撐服務;
模塊組件目錄:是服務初始化、銷毀以及業務前、後置模塊組件的父目錄;
銷毀模塊組件目錄:是服務進程銷毀時執行的模塊單元;
初始化模塊組件目錄:是服務進程初始化時執行的模塊單元;
業務後置模塊組件目錄:是服務線程在執行業務邏輯模塊組件後執行的模塊單元;
業務前置模塊組件目錄:是服務線程在執行業務邏輯模塊組件前執行的模塊單元;
業務處理模塊組件目錄:是服務業務處理的核心邏輯單元;
定時器模塊組件目錄:是服務整個生命周期內運行的定時器執行模塊單元;
微容器會根據以上約定分別在容器內掃描服務單元以及服務單元內各模塊執行的組件單元。此外,微容器可以通過兩種方式識別出服務單元,一種就是以上的“明文工程”模式,也就是源碼工程;而另一種是jar包形式,可以對服務源碼工程打包成“kingworks-xxxsmp/sop-v.jar”格式的jar引入容器工程裏,其中xxx就是服務標識,而v就是服務版本號,這也就是所謂的微服務插件化架構模式。
(微)服務樣例:service
testsop為本(微)服務演示樣例,其中kingwors-msac-3.0.0就是我們的微容器,Talk is cheap,show the code:
啟動微容器(服務),通過以下URI即可訪問:
(微)服務樣例:serviceBefore
serviceBefore模塊組件顧名思義也就是service業務處理模塊執行前的一個前置執行組件單元,有點類似於Filter的角色,Demo如下所示:
啟動微容器(服務),通過以下URI即可訪問:
(微)服務樣例:serviceAfter
serviceBefore模塊組件顧名思義也就是service業務處理模塊執行後的一個後置執行組件單元,如果結合業務前置模塊來使用,這就是一種約定的AOP模式,Demo如下所示:
啟動微容器(服務),通過以下URI即可訪問:
(微)服務樣例:contextInitialized
contextInitialized是服務單元初始化時容器會掃描執行的模塊組件單元,Demo如下所示:
啟動微容器(服務):
(微)服務樣例:contextDestroyed
contextDestroyed是服務單元銷毀時容器會掃描執行的模塊組件單元,Demo如下所示:
啟動微容器(服務):
(微)服務樣例:timer
timer是服務單元在啟動時會掃描執行的模塊組件單元,在整個服務生命周期內執行,Demo如下所示:
啟動微容器(服務):
(微)服務管控
其實“微容器”本身也是一個擁有標準服務單元目錄結構的服務,如下所示:
微容器的所有管控行為都是一樣通過服務標準六大模塊組件單元執行管控的,例如“服務的註冊”是在容器服務的初始化模塊組件中執行,“服務的註銷”是在容器服務的銷毀模塊組件中執行,“服務的心跳”、“服務的發現”以及“遠程配置同步”都是在容器服務的定時器模塊組件中執行,“服務的訪問限制”和“服務的並發限制”都是在服務前置模塊組件中執行的。此外,容器還擁有自身的service業務處理單元(“^KINGWORKS_000”業務標識歸屬於容器服務所有),這些業務處理單元暴露了容器的一些基本管控和信息輸出,如遠程配置實時更新通知、容器服務狀態信息查詢等,如下Demo所示:
(微)服務管理
微容器除了對基本的服務屬性、狀態信息等基本服務信息管理外,還充當了統一信息配置與統一RPC服務信息管理兩大“功能”。
【服務屬性信息】
namespace:命名空間,容器內置默認值為default
serverCode:服務標識
IP:協議地址,當IP為空時,容器動態獲取本地IP
port:服務端口,容器內置默認值為80
scope:服務範圍(private:自己可見|default:同命名空間可見|protect:同命名空間或子命名空間可見|public:所有服務可見),容器內置默認值為default
zone:服務領域(私域標識),當[zone=public]時,表示該服務為公域信息配置(非服務實例,不能註冊,混合雲關鍵點所在),容器內置默認值為default
weight:服務權重(0~9),容器內置默認值為2
【服務狀態信息】
服務總體並發以及各業務處理並發信息
服務網關調用狀態信息(如RPC連接池信息、服務熔斷次數、RPC狀態信息等)
數據庫連接池實體狀態信息
Redis連接池實例狀態信息
Kafka連接池實體狀態信息
......
【統一信息配置】
微容器規範約束的配置文件有:
kingworks.properties:微容器服務基本信息管理與控制
rdc.yml:服務註冊發現中心靜態配置信息
datasource.properties:關系數據庫配置信息
redis.properties:Redis配置信息
kafka.properties:Kafka配置信息
以上五大配置文件的配置規範都是微容器有一定的要規範配置格式,如關系數據庫配置信息文件,poolName就是數據庫連接池實例名稱,如果沒有特別指定,微容器的數據適配器組件(後續會介紹)默認會先選擇poolName=serverCode的數據庫連接池實例,如果不存在則匹配尋找poolName=default的數據庫連接池實例。
統一信息配置除了統一靜態解析之外,還可以通過配置conf服務進行動態解析,無論是靜態解析還是遠程動態解析,對服務內部調用來說完全是透明的。服務內部實現還可以通過對文件變動的動態監聽,以便實時做出處理。
【統一RPC服務信息管理】
rdc.yml(服務註冊發現中心信息配置文件)就是RPC匹配的一個服務信息中心,當系統初期階段為“單體模式”的時候,可以通過走“靜態服務解析”模式,也就是把所有的服務信息填寫(註冊)在這個文件下即可達到本地靜態服務註冊發現中心的效果。就算後續服務模式擴展改成動態加載模式,只需要配置rdc服務即可,對服務業務調用邏輯來說完全是透明的,無須改動任何一行代碼。
【統一日誌信息輸出管理】
微容器對日誌輸出一共有三種規範化約定模式,分別是標準輸出、文件輸出、流輸出(Kafka)三種模式,可通過kingworks.properties文件進行配置:
微容器的日誌輸出管理是通過logback引擎自定義以上三種日誌模式Appender,有著高約束和規範的日誌屬性和輸出格式(JSON):
(微)服務適配
微容器把服務以外的對接中間件工具組件統稱“適配器”,例如數據庫連接適配器,Redis連接適配器組件,遠程過程調用適配器組件等。
【數據庫連接適配器】
數據庫連接適配器組件是微容器高約束規則並基於標準化原生JDBC的API進行封裝的,具體使用如下Demo所示:
以上Demo是通過testsop服務的KINGWORKS_001_001_002業務實現單元實現的,通過URI訪問即可刪除相關查詢信息:
【遠程過程調用適配器組件】
微服務跟傳統系統最大的一個差別之一就是服務的信息交互已經多樣化,例如數據庫、內存數據庫、服務與服務之間交付等,已經弱化了傳統數據源的概念,這也是“適配器”統稱的來源。
只要微容器存在服務信息(無論是本地靜態解析還是遠程動態解析),RPCClient即可根據serverCode、serviceCode以及請求參數即可進行服務遠程過程調用,其中調用過程的一些列動作如負載、路由、降級、服務訪問權限、以及誇私有雲訪問等過程都已經被RPCClient封裝起來,我們可以通過kingworks.properties配置文件對服務遠程過程調用進行個性化配置。
微服務切面服務:BASESMP/SOP
basesop是所有sop服務的基礎切面服務,basesmp是所有smp服務的基礎切面服務,何為基礎切面服務,請看下圖所示:
通過上述介紹可以知道,微容器本身也內置了一個框架(Framework)級別的服務,其實框架服務、基礎切面服務以及業務服務的各個模塊的執行過程和順序就如上圖所示。嚴格來說,基礎SMP/SOP切面服務是所有SMP/SOP的切面服務,那麽微容器框架服務是所有服務的最頂層切面服務。基礎切面服務跟框架服務一樣,不是一個獨立的業務服務,更多是所有業務服務的上一層抽象。例如所有SMP服務都會有一個公共的前置操作(如會話驗證),可以通過BASESMP的serviceBefore實現即可達到所有SMP服務的公共前置操作。其它組件一樣道理,但有一點跟微容器框架服務有點相似,基礎切面服務的service如果實現了某業務邏輯實現,那麽此業務邏輯實現的標識不會在其它業務服務上生效,因為為容器先會在基礎切面服務檢測才到業務服務檢測。以下測試是在testsop服務的基礎上新增一個basesop服務的引用,basesop服務的所有組件實現跟testsop服務一樣,具體演示過程如下:
啟動服務後,我們通過console的打印信息觀察testsop服務與basessp服務之間的關系:
微服務模式
KingWorks微容器抽象了服務單元的實現,讓應用系統架構的模式切換對服務來說完全是透明的,當系統在“單體”模式的時候,更多是處於一種靜態服務解析模式:
當應用系統規模到一定程度時,可以對原單體應用模式進行擴展,進入分布式模式:
分布式模式並不代表一定使用服務動態解析(服務遠程註冊發現中心),如果業務相抵穩定,其實還是可以保留rdc.yml配置文件的靜態解析,省去了動態的成本和不確定性。如果系統發展到一定業務規模,其實系統還可以發展成為混合雲分布式模式:
由於KingWorks微服務“zone”和“scope”屬性的定義,可以讓不同私有域的服務通過公有域的入口進行遠程相互調用。在微容器的支撐下,最為突出和困難反而是對服務業務領域邊界的定義與抽象的設計。
微服務總結
以上的總結,僅僅只是微容器的一些基本玩法,受限於自己的文章篇幅控制,更多好玩的玩法和思路以後會慢慢分享。同樣由於諸多因素的受限和考慮,暫時無法公開源碼,但我更願意分享和記錄整個解決問題的思考過程。其實,KingWorks已經不僅僅只是一個框架,它承載更多地是我解決問題的一種思維方式的體現,它的內涵也不僅僅只是通過KingWorks微容器的數千行代碼就能體現,基於KingWorks之上的,還有一整套基於微服務(應用)雲上運用“雲開發”模式的一個“應用雲容器” ......
一個微服務框架的細節