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