定義應用程序的架構三步:
1、定義系統操作
2、定義服務
3、定義服務API和協作方式
一、識別系統操作
起點:需求(包括用戶故事及其相關的用戶場景)
步驟:
1、創建由關鍵類組成的抽象領域模型(關鍵類提供用於描述系統操作的詞彙表)
2、確定系統操作,並根據領域模型描述每個系統操作的行爲。
領域模型主要源自:用戶故事中提到的名詞。
系統操作主要來自:用戶故事中提到的動詞。
系統操作類型:
1、命令型:創建、更新、刪除數據
2、查詢型:查詢和讀取數據
二、定義微服務架構
2.1 服務拆分
策略一:根據業務能力進行服務拆分(前提:業務穩定)
策略二:根據子域進行服務拆分
DDD:領域驅動設計;其特別重要的兩個概念:子域和限界上下文。
領域爲每個子域定義單獨的領域模型。子域是領域的一部分,領域是DDD中用來描述應用程序問題域的一個術語。
識別子域的方法:分析業務並識別業務的不同專業領域【和識別業務能力方式一樣,結果也接近】
限界上下文:領域模型的邊界。它包括:實現模型的代碼集合。
當使用微服務架構時,每個限界上下文對應一個或一組服務。
總結:微服務架構設計工作--通過DDD方式定義子域,把子域對應爲每個服務。
2.2 拆分指導原則(源於面向對象設計)
原則一:定義類的職責,遵循單一職責原則
軟件架構和設計的主要目的之一是確定每個軟件元素的職責。
單一職責原則:改變一個類應該只有一個理由。---Robert C.Martin
遵循SRP原則,所定義的每一個類都應該只有一個職責。
設計微服務架構時應遵循SRP原則,設計小的、內聚的、僅僅含有單一職責的服務,這會縮小服務的大小並提升它的穩定性。
原則二:類組成包,遵循閉包原則(CCP)
閉包原則:
在包中包含的所有類應該是對同類的變化的一個集合。也就是說,如果對包作出修改,需要調整的類應該都在這個包之內。
----Robert C.Martin
如果由於某些原因,兩個類的修改必須耦合先後發生,那麼就應該把它們放在同一個包內。這樣做的目的是,當業務規則發生變化時,開發者只需要對一個交付包做出修改,而不是大規模修改(和重新編譯)整個應用。
採用閉包原則,可以極大改善應用程序的可維護性。
CCP是解決分佈式單體的法寶。
2.3 服務的分解障礙
1、網絡延遲(因爲服務之間的網絡往返太多)
解決方案:
第一種:批處理API在一次往返過程中獲取多個對象,從而將延遲減少到可接受的數量
第二種:把多個相關往返的服務組合在一起,用編程語言的函數代替昂貴的進程間通信。
2、服務之間的同步通信降低了可用性
解決方案:異步
3、需要維護跨服務的數據一致性。(需要使用Saga)
Saga:一系列使用消息協作的本地事務。Saga的一個限制是:它們最終是一致的。
如果需要以原子方式更新某些數據,那麼它必須位於單個服務中,這可能是分解的障礙。
4、獲取一致的數據視圖(無法跨多個數據庫獲得真正一致的數據視圖)
在微服務架構中,即使每個服務的數據庫一致,也無法獲得全局一致的數據視圖。
如果需要一些數據的一致視圖,那麼它必須駐留在單個服務中。
5、上帝類(God Class)(可以使用領域驅動設計的概念消除)
上帝類:在整個應用程序中使用的全局類。通常爲應用程序的許多不同方面實現業務邏輯,它有大量字段映射到具有許多列的數據庫表。
上帝類將應用程序的許多方面的狀態和行爲捆綁在一起。
三、定義服務API
服務API:服務的操作和事件。
存在服務API操作的原因:
1、某些操作對應於系統操作。由外部客戶端調用,也可能由其他服務調用。
2、存在一些其他操作用以支持服務之間的協作,這些操作僅由其他服務調用。
定義服務API的步驟:
1、將每個系統操作映射到服務;
分配方式:
1、將操作分配給需要操作所提供信息的服務;
2、將操作分配給具有處理它所需信息的服務
2、確定服務是否需要與其他服務協作以實現系統操作;
3、如果需要協作:確定其他服務必須提供哪些API才能支持協作。
筆記來自:《微服務架構設計模式》一書,作者 [美] 克里斯·理查森 著,喻勇譯