微服務(wù)基本特性
如何去定義微服務(wù)架構(gòu)呢沉颂?首先從MartinFowler微服務(wù)這篇博客中就能看出一些端倪个初。MartinFowler將微服務(wù)的特性總結(jié)為9條沈堡。
- “組件化”與“多服務(wù)”
- 圍繞“業(yè)務(wù)功能”組織團隊
- “做產(chǎn)品”而不是“做項目”
- “智能端點”與“傻瓜管道”
- “去中心化”地治理技術(shù)
- “去中心化”地管理數(shù)據(jù)
- “基礎(chǔ)設(shè)施”自動化
- “容錯”設(shè)計
- “演進式”設(shè)計
簡單來解釋下每個特性所表達的含義, 詳細可閱讀原文浪听。
“組件化”與“多服務(wù)”主要是對于組件以及服務(wù)做了定義螟碎,簡單可理解為組件例如一個libraries,能被鏈接到一段程序馋辈。服務(wù)的定義為需要通過web請求或遠程調(diào)用來進行通信。
圍繞“業(yè)務(wù)功能”組織團隊倍谜,想要表現(xiàn)的特性源于公司在做大型系統(tǒng)的架構(gòu)時候往往會聚焦在技術(shù)層面上迈螟,比如有專門的網(wǎng)關(guān)開發(fā)、業(yè)務(wù)開發(fā)尔崔、數(shù)據(jù)庫運維等等(本司也是)答毫。但是根據(jù)康威定律的指導(dǎo)原則
任何設(shè)計(廣義上的)系統(tǒng)的組織,都會產(chǎn)生這樣一個設(shè)計季春,即該設(shè)計的結(jié)構(gòu)與該組織的溝通結(jié)構(gòu)相一致洗搂。——梅爾文?康威(Melvyn Conway), 1967年
微服務(wù)使用不同的方法來分解系統(tǒng),即根據(jù)業(yè)務(wù)功能(business capability)來將系統(tǒng)分解為若干服務(wù)耘拇。這些服務(wù)針對該業(yè)務(wù)領(lǐng)域提供多層次撵颊、廣泛的軟件實現(xiàn),包括用戶界面惫叛、持久性存儲以及任何對外的協(xié)作性操作倡勇。因此,團隊是跨職能的嘉涌。
“做產(chǎn)品”而不是“做項目”主要是源自亞馬遜的“誰構(gòu)建妻熊,誰運行”的理念,開發(fā)工作也可以遵循上述“產(chǎn)品”理念仑最。
“智能端點”與“傻瓜管道”扔役,主要是體現(xiàn)微服務(wù)使用一些簡單的REST風(fēng)格的協(xié)議,而不使用服務(wù)的協(xié)議編排通信警医。
“去中心化”地治理技術(shù)和“去中心化”地管理數(shù)據(jù) 顧名思義想要表明微服務(wù)的特性是服務(wù)是單獨存在亿胸,單獨建模的。對于該特性在業(yè)務(wù)落地建模時候法严,常常使用DDD去實現(xiàn)损敷,關(guān)于DDD的學(xué)習(xí),我非常推薦徐昊老師的《如何落地業(yè)務(wù)建纳钇。》課程拗馒。
“基礎(chǔ)設(shè)施”自動化的想要表達的理念也非常明顯,需要構(gòu)建自動化的CI/CD pipeline溯街,常常需要我們建立完善的DevOps體系诱桂。
- “容錯”設(shè)計和 “演進式”設(shè)計 主要是表明微服務(wù)的設(shè)計要需要有技術(shù)手段來保證當(dāng)其中一個服務(wù)故障時候,通過如重試呈昔、降級等技術(shù)實現(xiàn)容錯挥等,另外整個業(yè)務(wù)的迭代在范圍內(nèi)要可控變化,實現(xiàn)演進堤尾。
微服務(wù)定義架構(gòu)
本文將限定于定義架構(gòu)肝劲,而非技術(shù)實現(xiàn),也就是說本文內(nèi)容是講解一種定義問題的方法郭宝,而非解決問題的方法辞槐。從微服務(wù)落地的現(xiàn)狀來看,往往在對架構(gòu)的定義和業(yè)務(wù)的分解上就出現(xiàn)了偏差粘室,在之后的技術(shù)實現(xiàn)上榄檬,用上了分布式技術(shù)的屠龍之術(shù),如鏈路追蹤衔统、限流鹿榜、熔斷等海雪,反倒導(dǎo)致了整個開發(fā)流程和維護流程熵值急劇升高。
在上節(jié)簡單介紹了微服務(wù)的基本特性舱殿,從以上的特性我們能看出來奥裸,我們要定義一個系統(tǒng)的微服務(wù)架構(gòu),關(guān)鍵有兩點怀薛,即
- 定義微服務(wù)的方式圍繞業(yè)務(wù)概念而非技術(shù)概念
- 服務(wù)的業(yè)務(wù)拆分有詳細的限界來保證變化可控
這里我們需要引入DDD來解決這兩個問題刺彩。通過子域進行分解;通過每個領(lǐng)域單獨的領(lǐng)域模型來消除依賴項枝恋。也就是上帝類创倔。通常來講DDD的建模沒有一個標(biāo)準(zhǔn)化的流程可以遵循,我們只能介紹一個大概的方法焚碌。以下我們將通過三個步驟畦攘,領(lǐng)域建模 -> 服務(wù)拆分 -> 定義服務(wù)API 來定義一個微服務(wù)項目的架構(gòu)流程。
領(lǐng)域建模
進行領(lǐng)域建模需要三個步驟:
- 確定領(lǐng)域事件
- 定義聚合
- 定義限界上下文
這里我們簡單用一段用戶故事來做整個流程串聯(lián)
我打算做一個外賣平臺叫“餓了團”十电,主要的功能有知押,用戶從我的平臺下單,然后我平臺接單之后鹃骂,分配給餐館商家台盯,商家接單進行制作,然后再由平臺分配騎手去進行配送給用戶畏线。騎手的位置會實時更新静盅,用戶可用通過平臺查詢到騎手的位置。
確定領(lǐng)域事件
在項目開始的起點寝殴,我們先需要根據(jù)用戶故事和用戶場景來識別和定義項目的基本操作蒿叠。
定義系統(tǒng)的操作主要是根據(jù)用戶故事中的動詞,我們也可以用事件風(fēng)暴(Event Storming)來定義領(lǐng)域驅(qū)動模型蚣常。
從上述的簡單用戶故事中市咽,我們能得到收斂出一些領(lǐng)域事件:用戶、商家抵蚊、訂單施绎、外賣配送、騎手位置贞绳。
好了谷醉, 同時我們也能總結(jié)出一些系統(tǒng)操作:下單、接單熔酷、更新騎手的位置孤紧、騎手已取餐豺裆、騎手正在配送拒秘、騎手配送完成号显。
定義聚合
接下來我們就需要根據(jù)這些領(lǐng)域事件找出聚合根,然后為每個聚合根關(guān)聯(lián)這些重要的系統(tǒng)操作躺酒。
確定聚合根押蚤,具體來講是屬于業(yè)務(wù)的一種sence,在復(fù)雜的業(yè)務(wù)場景中有不同的定義方式羹应,這里我們給出一種聚合根的定義揽碘,即把 商家、用戶园匹、騎手作為聚合根雳刺。
聚合根 | 系統(tǒng)操作 | 依賴的實體 |
---|---|---|
用戶 | 創(chuàng)建訂單、查詢訂單 | 訂單 |
商家 | 接受訂單裸违、準(zhǔn)備訂單掖桦、查詢訂單 | 訂單 |
騎手 | 更新位置、取餐供汛、配送枪汪、接受配送訂單 | 外賣配送 、位置怔昨、訂單 |
我們可以看到雀久,創(chuàng)建訂單操作被聚合用戶子域,接受訂單被聚合到了商家子域趁舀,但是考慮到訂單的查詢赖捌、以及訂單的狀態(tài)更新記錄等操作,如果聚合到上述的三個聚合根中明顯是不恰當(dāng)?shù)暮毡啵赃@里我們增加訂單子域來承擔(dān)訂單的查詢與狀態(tài)更新這些操作巡蘸。
定義限界上下文
可以看到,我們把訂單所承擔(dān)的功能都拆分為“多個”訂單實體擂送,放在不同的子域內(nèi)悦荒。所以這里的限界上下文對應(yīng)每個子域,通常而言嘹吨,限界上下文對應(yīng)為一個或者一組服務(wù)搬味。一個子域?qū)?yīng)為每一個服務(wù)。
服務(wù)拆分
對于服務(wù)的拆分我們很難給出標(biāo)準(zhǔn)性的答案蟀拷,這里可以給出一些指導(dǎo)原則碰纬。來源于Bob Martin的《面向?qū)ο笤O(shè)計的原則》 中的其中兩項。其余九個原則问芬,在設(shè)計類和包時非常有用悦析。
指導(dǎo)原則
- 單一職責(zé)原則
改變一個類只改有一個理由。
我們設(shè)計微服務(wù)架構(gòu)的時候也應(yīng)該遵循SRP原則此衅,設(shè)計小的强戴、內(nèi)聚的亭螟、僅包含一個職責(zé)的服務(wù)。
- 閉包原則
在包中包含的所有類應(yīng)該是對同類的變化的一個集合骑歹,也就是說预烙,對包做出的修改,需要調(diào)整的類都應(yīng)該在這個包內(nèi)道媚。
這個原則的目標(biāo)是扁掸,當(dāng)業(yè)務(wù)規(guī)則發(fā)生變化時候,開發(fā)者只需要對一個交付包做修改最域,而不是大規(guī)模的修改谴分。這樣可以極大的改善應(yīng)用程序的可維護性。
根據(jù)我們之上建模的例子镀脂,服務(wù)很容易拆分為四項
拆分服務(wù) | 對應(yīng)子域 |
---|---|
Consumer Service | 用戶子域 |
Order Service | 訂單子域 |
Restaurant Service | 商家子域 |
Delivery Service | 送餐子域 |
定義服務(wù)API
在這一步需要定義服務(wù)協(xié)作所需要的API狸剃,我們需要考慮到服務(wù)的前置條件和后置條件是否成立,比如
Consumer Service中我們需要驗證用戶的信息狗热,確認其是否支付即獲取付款信息钞馁。Restaurant Service中,需要驗證送貨地址和時間是否在餐廳的服務(wù)區(qū)域內(nèi)匿刮。所以我們部分API的定義如下所示:
服務(wù) | API |
---|---|
Consumer Service | verifyConsumerDetails() |
Order Service | findOrderDetailByConsumerId() |
Restaurant Service | verifyOrderDetails()僧凰、acceptOrder()、noteOrderReadyForPickup() |
Delivery Service | scheduleDelivery()熟丸、 notifyCourier()训措、updateLocation() |
這里只列出來很少一部分API的設(shè)計,更多的設(shè)計需要在真正的實踐中探索光羞。
總結(jié)
定義微服務(wù)架構(gòu)的整體內(nèi)容基本流程到這就介紹完畢了绩鸣,我通過舉了建立一個外賣平臺的示例,從領(lǐng)域建模 -> 服務(wù)拆分 -> 定義服務(wù)API來說明了微服務(wù)架構(gòu)將如何被定義纱兑,當(dāng)然我的示例中只是包含了非常有限的場景呀闻,如果要擴展開,其中可能還需要定義的有消費者的賬戶潜慎、餐廳的優(yōu)惠券捡多、餐館的關(guān)系、舉報投訴催單等等更加服務(wù)的業(yè)務(wù)關(guān)系铐炫±菔郑可以看到,這個過程是需要很強的業(yè)務(wù)sence倒信,勾勒出的架構(gòu)也是非常抽象的科贬。在微服務(wù)拆分階段,除了一些指導(dǎo)原則之外鳖悠,我們還會遇到很多難點榜掌。比如網(wǎng)絡(luò)延遲鸭丛、可用性、數(shù)據(jù)一致性等各類問題唐责,這時候就需要具體的分布式技術(shù)來解決這些問題。在后續(xù)的文章的瘾带,我將繼續(xù)展開鼠哥。
最后,關(guān)于微服務(wù)架構(gòu)看政,我還想說的是朴恳,架構(gòu)決定了軟件的各種非功能性因素,比如微服務(wù)架構(gòu)提高了可維護性允蚣、可測試性于颖、可部署性和可擴展性。但同樣嚷兔,在一些場景的性能方面有所妥協(xié)森渐。同時微服務(wù)架構(gòu)也增加了很多復(fù)雜性,比如在可觀測性冒晰、鏈路追蹤同衣、安全性等方面我們需要更多的第三方組件去協(xié)助解決。