微服務(wù)架構(gòu)拆分的七大黃金法則

微服務(wù)架構(gòu)拆分的 7 大黃金法則
你是否還在為微服務(wù)架構(gòu)的拆分而苦惱?本文揭秘 7 大拆分原則,助你輕松駕馭微服務(wù)架構(gòu)!
隨著云計算的普及,微服務(wù)架構(gòu)成為企業(yè)數(shù)字化轉(zhuǎn)型的重要選擇。
然而,如何合理拆分微服務(wù)卻成為許多開發(fā)者的難題。本文將揭秘 7 大拆分原則,助你輕松駕馭微服務(wù)架構(gòu),提升系統(tǒng)性能和可維護(hù)性。
無論你是架構(gòu)師還是開發(fā)者,這些原則都將為你帶來實實在在的幫助。
今天,碼哥帶大家從不同角度來剖析微服務(wù)架構(gòu)設(shè)計的 7 大原則,做到合理且正確地拆分出微服務(wù),避免打造一個被人詬病的偽微服務(wù)架構(gòu)大單體,徒增運維和開發(fā)成本。
1.一個反例
這是碼哥親身經(jīng)歷的一個事情,當(dāng)時我作為架構(gòu)師角色將公司原 saas 團隊的供應(yīng)鏈金融系統(tǒng)重新打造成一個標(biāo)準(zhǔn)化應(yīng)用,基于插件機制,業(yè)務(wù)開發(fā)只需要專注于功能,實現(xiàn)快速得到一個客戶想要的軟件。
該系統(tǒng)的團隊負(fù)責(zé)人帶著 IT 人的傲嬌對我說這是一個微服務(wù)架構(gòu)系統(tǒng)……
打開項目代碼發(fā)現(xiàn)這是一個披著微服務(wù)外衣的大單體巨石服務(wù)。

我真是太難了,該團隊的開發(fā)人員把這個系統(tǒng)拆分成了八九個‘微’服務(wù),可實際上業(yè)務(wù)功能系統(tǒng)壓力全集中在 web-service 服務(wù)上。
至于拆出來其他的“微”服務(wù),只干了一件事:Myabtis 作為 ORM 框架操作數(shù)據(jù)庫,我問他們?yōu)楹芜@樣拆?
對方的老開發(fā)一臉驕傲的說:“這樣可以做到單一職責(zé),解耦……”
單一職責(zé)不是這樣理解的,大兄弟。真的是「黛玉騎鬼火,該強的強,該弱的弱」。
鐵觀因:“碼哥,微服務(wù)架構(gòu)設(shè)計哪些原則可以指導(dǎo)我們正確的設(shè)計?避免設(shè)計出「依托答辯」的架構(gòu)?!?/span>
好問題,一共有 7 大原則可以幫助我們設(shè)計一個好的微服務(wù)架構(gòu)。
2.單一職責(zé)
簡單的就是最好的!
每個微服務(wù)都只負(fù)責(zé)一個單一的業(yè)務(wù),并確保做好這個業(yè)務(wù),保證微服務(wù)職責(zé)單一性、功能完整性拆分, 這樣,就便于維護(hù)、測試和部署。
另外,每個微服務(wù)都有自己的數(shù)據(jù)庫來存儲數(shù)據(jù),避免一個微服務(wù)與其他微服務(wù)共享數(shù)據(jù)庫,在數(shù)據(jù)層解耦,以確??蓴U展性和可靠性。

3.基于可靠性拆分
Dora:這個我懂,不能讓一顆老鼠屎搞壞一鍋湯。
你這么理解沒毛病。
在單體應(yīng)用中,一個組件的故障可能導(dǎo)致整個系統(tǒng)的崩潰。
通過微服務(wù)架構(gòu),我們可以將系統(tǒng)拆分為多個獨立的服務(wù),從而將故障隔離在單個服務(wù)內(nèi),避免故障擴散到整個系統(tǒng)。
將可靠性要求高的核心服務(wù)和可靠性要求低的非核心服務(wù)拆分開來,然后重點保證核心服務(wù)的高可用。
當(dāng)重要策劃高難度較低的服務(wù)發(fā)生故障時,不會影響核心模塊的服務(wù)。
比如將賬號信息、登錄信息、服務(wù)中心等重要度最高的要害模塊單獨拆分在一個服務(wù)顆粒上(因為這類模塊不可用之后,整個系統(tǒng)基本完全癱瘓),再做成服務(wù)集群,來保障它的高可用。
4.DDD 領(lǐng)域驅(qū)動原則
微服務(wù)架構(gòu)設(shè)計其實非常采用 DDD。因為每個微服務(wù)本就可以設(shè)計成特定領(lǐng)域的實現(xiàn)。
基于領(lǐng)域模型拆分,圍繞業(yè)務(wù)領(lǐng)域按職責(zé)單一性、功能完整性拆分。
- 戰(zhàn)略設(shè)計主要從業(yè)務(wù)視角出發(fā),建立業(yè)務(wù)領(lǐng)域模型,劃分領(lǐng)域邊界,建立通用語言的限界上下文,限界上下文可以作為微服務(wù)設(shè)計的參考邊界。
 - 戰(zhàn)術(shù)設(shè)計則從技術(shù)視角出發(fā),側(cè)重于領(lǐng)域模型的技術(shù)實現(xiàn),完成軟件開發(fā)和落地,包括:聚合根、實體、值對象、領(lǐng)域服務(wù)、應(yīng)用服務(wù)和資源庫等代碼邏輯的設(shè)計和實現(xiàn)。
 
使用 DDD(領(lǐng)域驅(qū)動建模) 進(jìn)行業(yè)務(wù)建模,從業(yè)務(wù)中獲取抽象的模型(例如訂單、用戶),根據(jù)模型的關(guān)系進(jìn)行劃分限界上下文。
從 DDD 的限界上下文往微服務(wù)轉(zhuǎn)化,并得到系統(tǒng)架構(gòu)、API 列表、集成方式等產(chǎn)出。
限界上下文可以視為邏輯上的微服務(wù),或者單體應(yīng)用中的一個組件。
Dora:“碼哥,如何找到系統(tǒng)的邊界呢?愛情起碼還能根據(jù)生理上的喜歡來輔助判斷?!?/p>
DDD 邊界上下文可以通過事件風(fēng)暴來找到,把系統(tǒng)狀態(tài)做出改變的事件作為關(guān)鍵點,從系統(tǒng)事件的角度觸發(fā),提取能反應(yīng)系統(tǒng)運作的業(yè)務(wù)模型。
再進(jìn)一步識別模型之間的關(guān)系,劃分出限界上下文,可以看做邏輯上的微服務(wù)。
例如系統(tǒng)管理員可以創(chuàng)建商品、上架商品,對應(yīng)的系統(tǒng)狀態(tài)的改變是商品已創(chuàng)建、商品已經(jīng)上架;
相應(yīng)的顧客創(chuàng)建訂單、支付,對應(yīng)的系統(tǒng)狀態(tài)改變是訂單已創(chuàng)建、訂單已支付。
商家發(fā)貨:選擇快遞公司、顧客填寫收貨地址……

5.按照業(yè)務(wù)穩(wěn)定性原則
這個很容易理解,需要區(qū)分系統(tǒng)中變與不變的部分,不變的部分一般是成熟的、通用的服務(wù)功能。
變的部分一般是改動比較多的需求、滿足業(yè)務(wù)迭代擴展性需要的功能,我們可以將不變的部分拆分出來,作為共用的服務(wù),將變的部分獨立出來滿足個性化擴展需要。
根據(jù)二八原則,系統(tǒng)中經(jīng)常變動的部分大約 20%,80% 是很少變動的,這種拆分方式還能避免 80% 那部分服務(wù)的頻繁發(fā)布。
比如一個電商系統(tǒng),用戶信息、商品信息等管理模塊一般是比較穩(wěn)定的;而運營類的活動和頁面是經(jīng)常變化的。

6.基于吞吐量原則
這是一個拓展原則,是針對特定場景的微服務(wù)拆分,簡單的說就是訪問量特別大,訪問頻率特別高的業(yè)務(wù),又要保證高效的響應(yīng)能力,這些業(yè)務(wù)對性能的要求特別高。
比如積分競拍、低價秒殺、限量搶購。
盡可能把這部分業(yè)務(wù)拆分出來,既能保證高性能的要求,又能保證業(yè)務(wù)的獨立性。
如果這種訪問量巨大的業(yè)務(wù)如果與其他通用業(yè)務(wù)放一塊,很容易因為某個鏈路阻塞,導(dǎo)致雪崩效應(yīng)影響其他業(yè)務(wù)。

7.演進(jìn)式原則
微服務(wù)拆分并不是一步到位的,應(yīng)當(dāng)根據(jù)實際情況逐步展開。
如果一開始不知道應(yīng)該劃分多細(xì),完全可以先粗粒度劃分,然后隨著需要,適當(dāng)將粒度劃分更細(xì)拆分。
Chaya:如果拆分粒度太細(xì)會增加運維復(fù)雜度,粒度過大又起不到效果,那么改造過程中如何平衡拆分粒度呢?
從兩個方面做權(quán)衡,一是業(yè)務(wù)發(fā)展的復(fù)雜度,二是團隊人員規(guī)模。
比如一個電商一開始索性可以拆分為商品服務(wù)和交易服務(wù),一個負(fù)責(zé)展示商品,一個負(fù)責(zé)購買支付。
隨后隨著交易服務(wù)越來越復(fù)雜,就可以逐步的拆分成訂單服務(wù)和支付服務(wù)、庫存服務(wù)、價格服務(wù)、物流服務(wù)等等。
雖然業(yè)務(wù)復(fù)雜度已經(jīng)滿足了,如果公司此時沒有足夠的人力(招聘不及時或員工異動比較多),服務(wù)最好也不要拆分,拆分會因為人力的不足導(dǎo)致更多的問題,如研發(fā)效率大幅下降(一個開發(fā)負(fù)責(zé)與其不匹配數(shù)量的服務(wù))。
Chaya:戀愛是兩個人的事,3+ 以上就大亂了,所以一個微服務(wù)究竟需要幾個開發(fā)維護(hù)是比較合理呢?
三個!
系統(tǒng)規(guī)模
從系統(tǒng)規(guī)模來講,3 個人負(fù)責(zé)開發(fā)一個系統(tǒng),系統(tǒng)的復(fù)雜度剛好達(dá)到每個人都能全面理解整個系統(tǒng),又能夠進(jìn)行分工的粒度。
如果是 2 個人開發(fā)一個系統(tǒng),系統(tǒng)的復(fù)雜度不夠,開發(fā)人員可能覺得無法體現(xiàn)自己的技術(shù)實力。
團隊管理
從團隊管理來說,3 個人可以形成一個穩(wěn)定的備份,即使 1 個人休假或者調(diào)配到其他系統(tǒng),剩余 2 個人還可以支撐。
如果是 2 個人,抽調(diào) 1 個后剩余的 1 個人壓力很大。
一個人更不用說了,如果他去大保健被抓了,系統(tǒng)出問題就沒人維護(hù)了。
技術(shù)提升
從技術(shù)提升的角度來講,3 個人的技術(shù)小組既能夠形成有效的討論,又能夠快速達(dá)成一致意見。
如果是 2 個人,可能會出現(xiàn)互相堅持自己的意見,或者 2 個人經(jīng)驗都不足導(dǎo)致設(shè)計缺陷。
一個人的話,沒人進(jìn)行技術(shù)討論,容易陷入思維盲區(qū)。
8.避免環(huán)形、雙向依賴
微服務(wù)拆分還有一個重要原則,就是避免環(huán)形、雙向依賴。
服務(wù)之間的環(huán)形/雙向依賴會使得服務(wù)間耦合加重,在服務(wù)升級的時候會比較頭疼,不知道應(yīng)該先升級哪個,后升級哪個,難以維護(hù)。
產(chǎn)生這種情況大多數(shù)是因為服務(wù)之間的調(diào)用可沒有約束導(dǎo)致,為了方便獲取或者更新某個表的數(shù)據(jù),服務(wù)之間任意調(diào)用。
也說明我們的功能劃分不夠清楚或者通用功能沒有下沉下來。

消除環(huán)形依賴的方法
要解決循環(huán)依賴,必須要在微服務(wù)之間建立一些原則來約束微服務(wù)之間的通信,定期通過這些原則來審視我們的系統(tǒng),找到問題并進(jìn)行重構(gòu),這些原則應(yīng)該包括:
- 定義服務(wù)上下游關(guān)系,上游服務(wù)可以直接依賴下游服務(wù),反之則不可。
 - 上游服務(wù)的變更對下游服務(wù)產(chǎn)生影響需要通過領(lǐng)域事件(異步)的方式來實現(xiàn)。
 - 服務(wù)之間要通過數(shù)據(jù) Id(或類 Id,能夠唯一代表數(shù)據(jù)且不變的屬性)來進(jìn)行關(guān)聯(lián),盡量不做過多的數(shù)據(jù)冗余。
 - 一旦需要上游服務(wù)調(diào)用下游服務(wù)才能完成業(yè)務(wù)時,要考慮是否上游服務(wù)缺少業(yè)務(wù)概念
 - 為滿足前端邏輯而導(dǎo)致的服務(wù)間交互邏輯要放到 BFF(Backend for frontend)中來編排,而不是增加服務(wù)間的調(diào)用。
 















 
 
 


 
 
 
 