前言
這是一本關於微服務架構設計方面的書,這是本人閱讀的學習筆記。首先對一些符號做些說明:
()為補充,一般是書本里的內容;
[]符號為筆者筆注;
1. 微服務架構到底是什么
1.1 軟件架構的4+1視圖
1.2 應用程序的兩個層面需求
- 功能性需求;
- 非功能性需求,又稱質量屬性需求。(包括可擴展性、可靠性、可維護性、可測試性與可部署性等)[這點是架構為什么重要的原因]
1.3 分層式架構風格
流行的三層架構是應用於邏輯視圖的分層架構,如下:
- 表現層:包含實現用戶界面或外部API的代碼;
- 業務邏輯層:包含業務邏輯;
- 數據持久層:實現與數據庫交互的邏輯;
其弊端是:
- 單個表現層:無法展現應用程序可能不僅僅由單個系統調用的事實;
- 單一數據持久化層:無法展示應用程序可能與多個數據庫進行交互的事實;
- 將業務邏輯層定義為依賴於數據持久化層:理論上,這樣是依賴會妨礙在沒有數據庫的情況下測試業務邏輯;
1.4 關於架構風格的六邊形
六邊形架構是分層架構風格的替代品 [解決分層架構的弊端],六邊形架構選擇以業務邏輯為中心的方式組織邏輯視圖。
圖解:
- 業務邏輯具有一個或多個端口,端口定義了一組操作,關於業務邏輯如何與外部交互。
- 有兩種端口:入站端口與出站端口;
- 入站端口是業務邏輯公開的API(如服務接口等,外部可以訪問);
- 出站端口是業務邏輯調用外部系統的方式(如儲存庫接口,定義數據訪問操作的集合);
- 業務邏輯周圍是適配器,有兩種適配器:入站適配器與出站適配器;
- 入站適配器:通過調用入站端口處理外部請求(如Spring MVC Controller,實現REST接口或一組Web界面);
- 出站適配器:通過調用外部應用程序或服務處理來自業務邏輯的請求(如實現數據訪問對象DAO類);
好處:
- 將業務邏輯與適配器中包含的表示層和數據訪問層的邏輯分離開,使單獨測試業務邏輯容易;
- 反映現代應用程序的架構;
1.5 什么是服務
服務是一個單一的、可獨立部署的軟件組件,它實現了一些有用的功能。
圖解:
- 服務具有API,為客戶端提供對功能的訪問;
- API由命令、查詢和事件組成;
- 開發人員無法繞過API直接訪問服務內部的方法或數據(松耦合);
1.6 微服務架構的架構風格
- 它實現的視圖由多個組件構成;
- 組件是服務,連接器是使這些服務能夠協作的通信協議;
- 松耦合;
- 共享類庫(里面實現不太可能改變的功能);
- 服務大小不重要;
2 為應用程序定義微服務架構
定義架構是一項藝術而非技術;在現實世界中,這是一個不斷迭代和持續創新的過程。
2.1 定義應用程序架構的三步式流程
- 第一步:識別系統操作;
- 第二步:定義服務;
- 第三步:定義服務API;
2.2 第一步:識別系統操作
抽象的領域模型與系統操作能夠回答這個應用“做什么”這一問題,有助於推動應用程序的架構設計。
2.2.1 識別系統操作的步驟與一些事項:
- 第一步:創建抽象領域模型;
- 可以通過分析用戶故事和場景中頻繁出現的名詞,經過迭代分析為這個領域模型的一些類;
- 第二步:定義系統操作;
- 識別系統必須的各種請求, 通常有兩種:
- 命令型:創建、更新或刪除數據的系統操作;
- 查詢型:查詢和讀取數據的系統操作;
- 系統操作的切入點在分析用戶故事和場景中頻繁出現的動詞;
- 需要考慮命令規范(參數、返回值和領域模型類)與行為規范(前置條件、后置條件);
- 識別系統必須的各種請求, 通常有兩種:
2.3 第二步:定義服務
2.3.1 根據業務能力進行服務拆分
拆分步驟:
- 首先要確定業務能力,通常指這個組織的業務是做什么,可以通過對組織的目標、結構和商業化流程分析得來;
- 確定了業務能力后,就可以為每個能力組定義服務,這是一個非常主觀的判斷;
- 下圖為FTGO應用程序從能力到服務的映射:
2.3.2 根據子域進行服務拆分
又稱:基於領域驅動設計分解應用程序的方法
一些概念:
- 領域模型:以解決具體問題的方式包含了一個領域的知識;
- DDD通用語言:定義了當前領域相關團隊的詞匯表,其有兩個重要概念:
- 子域:是領域的一部分,識別方式跟識別業務類似;
- 限界上下文:領域模型的邊界,通常每一個限界上下文對應一個或一組服務;
拆分步驟:
- 通過DDD的方式定義子域;
- 把子域對應為每一個服務;
- 下圖為FTGO應用程序從子域到服務的映射:
2.3.3 拆分的指導原則
受啟發於面型對象設計原則。
- 單一職責原則:定義的每一個類都應該只有一個職責;
- 閉包原則:如果出於某種原因,兩個類的修改必須耦合先后發生,那么就應該把它們放在同一個包內;
2.3.4 拆分單體應用為服務的難點
- 網絡延遲:
- 描述:對服務的特定分解導致兩個服務之間的大量往返調用;
- 解決:把多個相關服務組合在一起,用編程語言的函數調用替換進程間通信;或者實施批處理API在一次往返中獲取多個對象;
- 同步進程間通信導致可用性降低:
- 描述:使用REST協議同步調用其他服務時,會降低service的可用性;
- 解決:參考《第三章 異步消息》;
- 在服務之間維護數據一致性:
- 描述:當一個系統操作需要修改多個服務的數據時,需要維護數據的一致性;
- 解決:參考《第四章 Saga相關》;
- 獲取一致的數據視圖:
- 描述:無法跨多個數據庫獲得真正一致的數據視圖;
- 解決:(在實踐中很少帶來真正的問題);
- 上帝類阻礙了拆分:
- 描述:上帝類是在整個應用程序中使用的全局類,通常與多個服務的狀態與行為綁定;
- 解決:參考本章《2.3.5 上帝類阻礙了拆分》,以FTGO的Order類為例;
2.3.5 上帝類阻礙了拆分
在定義微服務架構時,必須識別並消除上帝類。
問題描述:在FTGO應用程序中,Order類與訂單處理、餐館訂單管理、送餐與付款等服務有關,具有復雜的狀態模型,如下圖所示;
解決方法:
- 將Order類打包到庫中並創建一個中央Order數據庫(違反松耦合原則);
- 將Order數據庫封裝在Order Service中,該服務由其他服務調用用以檢索和更新訂單(問題在於Order Service將成為一個純數據服務,成為很少或沒有業務邏輯的貧血領域模型);
- 【推薦】應用DDD將每個服務視為具有自己的領域模型的單獨子域,使每個與訂單有關的服務都有自己的領域模型及其對應的Order類版本,如下圖所示;
2.4 第三步:定義服務API
2.4.1 定義服務API的步驟與事項
- 第一步:把系統操作分配給服務;
- 即確定哪個服務是請求的初始入口點;
- 第二步:確定支持服務協作所需要的API;
- 某些系統操作完全由單個服務處理;也可能分散在多個服務周圍。
3. 本章小結
- 架構決定了軟件的各種非功能性因素,比如可維護性、可測試性、可部署性和可擴展性,它們會直接影響開發速度;
- 微服務架構是一種架構風格,它給應用程序帶來了更高的可維護性、可測試性、可部署性和可擴展性;
- 微服務中的服務是根據業務需求進行組織的,按照業務能力或者子域,而不是技術上的考量;
- 有兩種分解模式:
- 按業務能力分解,其起源於業務架構;
- 基於領域驅動設計的概念,通過子域進行分解;
- 可以通過應用DDD並為每個服務定義單獨的領域模型來消除上帝類,正是上帝類引起了阻礙分解的交織依賴項。
最后
