企業分解微服務的十條軍規
譯文【51CTO.com快譯】如果您的組織正打算采用和實施微服務,那么您一定聽說過諸如:領域驅動設計(Domain-Driven Design)、事件驅動架構(Event-Driven Architecture)、核心域(Core Domain)、子域(Subdomain)、限界上下文(Bounded Context),防腐層(Anti-corruption Layer)等概念。同時,您的團隊是否有能力以正確的方式,分解業務域邏輯(或稱業務空間),并將其與微服務架構(或稱代碼空間)相映射,以便受益于微服務架構帶來的優勢呢?
微服務分解架構邏輯圖
在本文中,我將為您總結分解微服務的十項原則與相關策略。
1.使用限界上下文和通用語言(Ubiquitous Language)來查看業務域
在進行分解之前,我們首先要做的是縮小產品所有者與開發人員之間的距離。產品所有者可能并不了解技術術語,而技術團隊也可能不了解術語在解釋業務中的重要性。因此,為了彌合這種“雞同鴨講”的差距,我們需要采取以下步驟:
- 將產品所有者聚攏到看板前,詢問他們:“業務目標是什么?”、“在特定功能中有什么角色?”、“他們在定義功能時使用了哪些術語?”這些問題將有助于技術人員弄清可能引起誤解的業務術語。例如“訂單上下文客戶”與“架構支持上下文客戶”之間的區別。
- 一旦理解了容易產生歧義的術語,請結合相關功能繪制出上下文,以保證在每個上下文中,每個域實體的名稱都足夠清晰。
- 為每個上下文定義一種通用語言,以便業務團隊和技術團隊在交流時,可以使用相同的通用語言進行同步。
- 先從一個粗粒度(coarse-grained)的限界上下文開始。除非以后出現了令人信服的業務理由,否則不再細分限界上下文。
2.確定核心域并運用創新思想
核心域是那些能夠為您的業務帶來收益的部分。對于B2C的在線購物應用而言,其購物車模塊便屬于核心域。我們需要通過思考如何改進那些競爭對手所不具備的模塊,以充分了解自己的核心模塊。任何自動化、或創新都會增加您的營收與優勢,因此你需要針對核心域進行重點研發和投入,以保持自身競爭優勢。
3.對通用域進行成本優化
通用域是每個企業所共有的部分。通常,不同的第三方會針對商業化市場,提供通用的解決方案。例如,各個業務配套的通知模塊,或是廣告推送模塊。為了避免重復“造輪子”,我們需要以成本優化的方式創建通用域,或是以相對便宜的價格,采用第三方解決方案。
4.適當考慮支持域
通常,核心域需要支持域的協助,來豐富自身。當然在某些情況下,支持域不但可以帶來收益,也可能在將來轉換為核心域。例如,在前面的例子中,相比購物車域,庫存管理屬于支持域。那么,通過對支持領域進行投入,也能夠產生營收。例如,為了降低運輸的成本,我們既可以選擇增加庫存的站點,又可以運用算法,識別客戶訂單最近的庫存位置。
5.引入防腐層
防腐層是微服務設計中不可或缺的部分,它可以保護微服務免受外界變化的影響。例如,在實際情況下,一些舊的項目會受到大型主機環境、或依賴某種語言的構建限制。由于它們是微服務輸入數據的重要來源,因此它們不但需要與微服務架構并存,甚至阻礙對系統進行分解。因此,在舊版架構和微服務通信之間創建外包層(facade),比起直接使用舊版中的數據,并在微服務和舊版架構上創建耦合,要好得多。
同時,由于通用域會調用第三方庫,我們與其根據合約直接使用(consume)/發布數據,不如引入一個防腐層,將微服務與外部合約的API,端口與hub模式隔離開來。也就是說,我們可以通過創建合約和防腐層,來充當微服務與第三方聯系間的“翻譯器”,以協助調用第三方庫。
6.識別數據通信模式
一旦您基于功能分解了微服務,并在核心服務中封裝了自己的數據庫與持久層(即,基于每個服務的數據庫),接下來需要理解的重要事項便是,UI的視圖/組件將如何與每個組件進行通信(包括流程)。例如:用戶在以異步的方式獲取某項功能時,您可以在執行部分功能后創建中間狀態,以便另一個系統對該中間狀態執行處理,并以回調的方式通知用戶繼續后續的操作。
7.引入事件驅動架構(EDA)
在實時應用中,您的業務用例可能具有復雜的工作流,并且需要根據數據的狀態變化,在工作流上產生許多分支。由于工作流程可以采取不同的策略,因此如果您需要通過Rest API公開所有的內容,則會發現每個微服務都需要與其他微服務耦合。這勢必會造成“意大利面”式的代碼和分布式的“泥球”。
可見,我們需要的是一個干凈的架構。其中每個微服務都可以獨立運行,而不會產生耦合。這正是事件驅動架構能夠起作用的地方--每個事件都能夠包含某個狀態的變化。微服務通過遵循pub/sub模型,產生狀態更改,并以事件的形式包含必要的數據。其他微服務則會偵聽該事件,并能夠基于事件中的數據,采取相應的策略。由于事件是不可變的,因此它也會保存實體或聚合器的歷史記錄。據此,如果您要采用事件存儲和事件風暴,則會生成相應的統計信息和事件報告。
8.讓API合約簡潔明了
在微服務中,您往往需要以API的形式,來發布合約。那么,在發布API時,請確保您的API不會發布內部狀態信息。考慮到網絡調用與封裝,發布API其實就是一種使其他服務可以獲取足夠的信息,以便繼續其流程的方式。不過,它們不應該為了獲取派生信息,而有多次返回。因此,在規劃事件時,您應該考慮哪些事件可以被發布,而哪些事件需要被保留在內部。您甚至可以只發布一個粗粒度的事件,而非多個小型內部事件。例如:如果您內部產生了地址更改事件和個人信息更改事件,那么就應該發布一個名為CustomerUpdateEvent的粗粒度事件,而不是在API合約中同時發布這兩者。
9.將相關的微服務合并為更大的服務
在分解之后,您可能會遇到在需要添加或更新功能時,某些微服務總會一起發生變化的情況。此時,您才會意識到自己以錯誤的方式分解了它。由于屬于同一邏輯單元的不同部分,因此它們一定不能夠被隔離到更小的服務中。對此,您可以將它們合并為一個大服務,以減少不必要的耦合和網絡調用。
10.引入支持無縫開發的工具
通過采用微服務,我們既可以提高可擴展性和高可用性,又能夠縮短產品上市的時間。不過由于該架構是基于分布式網絡工作的,因此在出現不可避免的故障之前,我們需要事先購置各種支持軟件。例如,您可以在CI/CD管道上采用云基礎架構,使用配套的跟蹤工具,采用日志聚合器來搜索日志,以及使用各種混沌工具(chaos tools)來檢測各種失敗。
原文標題:10 Commandments of Microservice Decomposition,作者:Shamik Mitradecomposition
【51CTO譯稿,合作站點轉載請注明原文譯者和出處為51CTO.com】