當DDD遇上微服務
DDD與微服務是可以相通的,其關鍵在于Bounded Context。
分布式系統的定義
在談論這個之前,我們需要就什么是分布式系統達成一致。在我看來,判斷一個系統是否是分布式的,其標準是看系統中是否存在跨進程通信。是進程決定了協作與通信的方式,從而引申出兩種具有本質區別的編程模型:
- 進程內編程模型
- 跨進程編程模型
它們之間的區別在于組件之間的調用方式。進程內的組件調用是非常簡單的,就Java而言,各個駐留于同一個JVM的對象與變量都放在堆內存或者棧內存中,對象的調用(包括方法的調用)就是一種內存的尋址。Java語言通過new關鍵字創建實例,從而獲得該實例的指針,以便于對該實例的屬性與方法進行調用。
跨進程組件之間的調用方式與進程內調用有著本質的。雖然跨進程通信機制存在各種不同的實現,但它們要考量的因素都是相同的,需要考慮:
- 進程間的通信協議
- 如何尋址
- 消息的序列化與反序列化
除此之外,在資源管理、事務一致性以及部署方面,都會因為跨進程通信的原因而產生巨大的差別。
顯然,跨進程通信固有的復雜度帶來了編程模型的改變,但它能夠更加有效地利用硬件資源,卻是分布式系統的主要目標。因此,在IT發展的當前歷史背景下,我們將進程作為邊界來定義分布式系統是非常有意義的。
說明:不同的語言平臺,進程的概念有細微差別,通信機制自然也有所不同。Java進程等同于操作系統的進程,但Erlang與Go的進程概念則不相同,要更加輕量級。
跨進程組件之間的調用方式其實是對通信機制的一種抽象,它其實又包含了:
- 進程間通信機制(如共享內存、管道、Socket)
- 結構化通信機制(如RPC)
- 中間件通信機制(分布式對象如CORBA、組件中間件如EJB、消息中間件、面向服務與REST)
討論C4模型的Container
Simon Brown提出了自己的C4模型,如下圖所示:
我們對Container的劃分,可以將進程作為劃分的邊界,即我認為的“物理邊界”。所以Container在架構中除了可以作為邏輯視圖的組成元素之外,也可以視為物理視圖的一部分。
無獨有偶,Alistair Cockburn提出的六邊形架構(又名port-adapter模式)在邊界含義上與Container是與之呼應的。下圖中外部六邊形的邊界就是一個物理邊界,按照之前的分析,我們可以將其視為進程邊界。
微服務與Bounded Context
微服務作為一個可以獨立部署的微小服務,天生就是一個在物理上隔離的自治服務。從物理視圖的角度看,一個微服務就是C4模型中的Container,也就是六邊形架構中的六邊形。如果我們將六邊形架構與DDD的Bounded Context對應起來,那么就可以引入DDD的戰略設計來劃分服務邊界,從而幫助我們進行微服務設計了。
一個典型的Bounded Context,可以具有自己的領域模型,訪問專有的數據庫,且可以引入“依賴注入”來滿足Uncle Bob所謂的Clean Architecture思想。下圖所示的Bounded Context的架構,不正是可以表現為一個微服務嗎?
Context Map對微服務的闡釋
思考DDD中的Bounded Context,可以重點把握以下兩點:
- Bounded Context與Domain之間的關系
- Context Map
倘若我們認為Bounded Context與Domain之間存在對應關系,就說明可以從業務架構的層面來設計微服務。通過用例、通用語言或者其他手段,都可以幫助我們識別Bounded Context,進而得到相對合理的服務邊界。
若要判斷微服務的設計是否合理,則可以通過DDD的Context Map進一步驗證和判別Bounded Context的劃分,并理清楚它們之間的關系。
Eric Evans在DDD一書中列出了九種Context Map,基本上可以歸類為:
- 團隊之間的協作方式
- 進程之間的集成方式
為什么說Bounded Context之間的關系可以理解為是團隊之間的協作方式呢?理論根據來自康威定律,即:
設計一個系統(此處泛指更廣泛的系統,而不僅僅是信息系統)的任何組織都必然會產生一個其結構是該組織通信結構副本的設計。 |
一個Bounded Context可能會映射到一個開發團隊,所以討論Bounded Context之間的關系,也可以視為是討論團隊之間的關系。至于進程之間的集成方式,無論是引入ACL(防腐層)還是OHS(開放主機服務),目的都是在實現進程間通信的同時,更好地做到Bounded Context之間的松散耦合。以微服務觀之,就是要滿足服務邊界足夠的自治性。
故而當DDD遇到微服務,其實有許多玄妙的相似之處值得深究。它們之間或許可以碰撞出感情的火花,也未可知呢。
【本文為51CTO專欄作者“張逸”原創稿件,轉載請聯系原作者】