為什么在做微服務(wù)設(shè)計(jì)的時(shí)候需要DDD?
掃描二維碼
隨時(shí)隨地手機(jī)看文章
作者:張飛洪
原文:www.cnblogs.com/jackyfei/p/12089123.html
記得之前在規(guī)劃和設(shè)計(jì)微服務(wù)架構(gòu)的時(shí)候,張隊(duì)長(zhǎng)給了我一個(gè)至今依然記憶深刻的提示:『你的設(shè)計(jì)藍(lán)圖里為什么沒有看到DDD的影子呢?』 隨著對(duì)充血模型的領(lǐng)域認(rèn)知的加深,我越加感覺到DDD的重要性。于是網(wǎng)上一頓海找,并做了學(xué)習(xí)筆記。 DDD內(nèi)容繁多,個(gè)人淺見,它不同于傳統(tǒng)貧血的最核心的一點(diǎn)就是把原先傳統(tǒng)的貧血模型里的業(yè)務(wù)邏輯層拎出來,融入到Domain層,這樣面對(duì)復(fù)雜業(yè)務(wù)的規(guī)模化變更,我們只需要專注于Domain即可。回到主題,我們要了解的是微服務(wù)和DDD到底有什么關(guān)系呢?
因?yàn)樵诨ヂ?lián)網(wǎng)時(shí)代,軟件所面臨的問題域比以往要復(fù)雜得多,這種復(fù)雜性來源于不斷擴(kuò)展的問題域自身,也來源于創(chuàng)新變化,以及這種規(guī)模性增長(zhǎng)所帶來的挑戰(zhàn)。
然而,一個(gè)人一個(gè)團(tuán)隊(duì),他對(duì)復(fù)雜的事物的認(rèn)知是有極限的,面對(duì)這種復(fù)雜問題唯一的方法就是分而治之。分主要考慮的是如何去分;治意味著分出來的每一個(gè)部分要能夠獨(dú)立的運(yùn)行,能夠互相的協(xié)作,完成整體的目標(biāo),能夠一來應(yīng)對(duì)外部變化所帶來的沖擊。
微服務(wù)的缺陷
??????微服務(wù)架構(gòu)在分和治兩個(gè)方面都給出了很好的理論指導(dǎo)和最佳實(shí)踐,那微服務(wù)是不是解決復(fù)雜問題的銀彈呢?其實(shí)不然,很多團(tuán)隊(duì)在應(yīng)用了微服務(wù)架構(gòu)來構(gòu)建他們的系統(tǒng)以后,發(fā)現(xiàn)并沒有完全解決這種復(fù)雜性問題,甚至還帶來了一些其他的問題。比如:- 服務(wù)并沒有解決復(fù)雜系統(tǒng)如何應(yīng)對(duì)需求變化這個(gè)問題,甚至還加劇了這個(gè)問題。
- 當(dāng)一個(gè)需求變化了,需要花大量的精力去識(shí)別這個(gè)變化影響到了哪些微服務(wù),這些服務(wù)的多個(gè)團(tuán)隊(duì)之間,需要通過無休止的扯皮去決定哪個(gè)服務(wù)多一些,哪些服務(wù)少改一些。
- 然后測(cè)試團(tuán)隊(duì)還需要做昂貴的這種聯(lián)調(diào)測(cè)試
- 即便如此呢,開發(fā)團(tuán)隊(duì)依然不放心,還要通過一系列的開關(guān)控制,小心翼翼的去做切流,去做灰度發(fā)布。
DDD功用
??????當(dāng)我們?nèi)プ龇值倪@種工作的時(shí)候,具體拆分詳見我的另外一篇文章《微服務(wù)的拆分姿勢(shì)》,需要考慮哪些維度呢?我覺得我們至少要考慮三個(gè)維度:- 功能緯度
- 質(zhì)量緯度,比如性能,可用性
- 工程緯度
??????微服務(wù)對(duì)第2個(gè)給出了很好的指導(dǎo),對(duì)第3個(gè)也給出了一些建議。但是,對(duì)第1個(gè)功能緯度只給出來非常有限的指導(dǎo),就是為什么隨著微服務(wù)的流行,領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)(DDD)又被重新重視起來的原因。
DDD彌補(bǔ)了微服務(wù)在功能劃分方面沒有給出很好指導(dǎo)的缺陷。所以他們?cè)诿鎸?duì)復(fù)雜問題和構(gòu)建系統(tǒng)時(shí)候是一種互補(bǔ)的關(guān)系,在系統(tǒng)拆分的時(shí)候可以很好的協(xié)作。 ??????只是他們看待系統(tǒng)拆分這個(gè)角度是不同的。微服務(wù)當(dāng)中的服務(wù)所關(guān)注的范圍正是DDD所推崇的六邊形架構(gòu)中的領(lǐng)域?qū)印?/span>?
拆分案例
接下來結(jié)合DDD和微服務(wù)來拆分一個(gè)復(fù)雜系統(tǒng)。關(guān)于領(lǐng)域
我們稱企業(yè)的業(yè)務(wù)范圍和在這個(gè)范圍里進(jìn)行的活動(dòng)為領(lǐng)域,和軟件系統(tǒng)無關(guān)。領(lǐng)域會(huì)分成多個(gè)子域,比如我們一個(gè)電商系統(tǒng),會(huì)有:- 商品子域
- 訂單子域
- 庫存子域等等。
劃分系統(tǒng)內(nèi)部架構(gòu)邊界
??????架構(gòu)簡(jiǎn)潔之道這本書里邊就說過:『系統(tǒng)架構(gòu)是由系統(tǒng)的內(nèi)部架構(gòu)邊界以及邊界之間的依賴關(guān)系所決定的,與系統(tǒng)中各個(gè)組件之間的通信和調(diào)用的方式是無關(guān)的』。我們常說的微服務(wù)的服務(wù)調(diào)用本身只是一種比函數(shù)調(diào)用方式成本稍高的,分割應(yīng)用程序行為的一種形式,系統(tǒng)架構(gòu)無關(guān)。 ??????所以,復(fù)雜系統(tǒng)劃分的第一重要的是要劃分內(nèi)部的架構(gòu)邊界,即劃分清楚這個(gè)上下文,以及明確他們之間的關(guān)系,這對(duì)應(yīng)于我們之前說的功能的維度。這正是DDD用武之處。其次我們才考慮基于非功能的維度如何劃分,這是微服務(wù)能夠發(fā)揮其優(yōu)勢(shì)的地方。 舉個(gè)例子,我們把系統(tǒng)分成ABC三個(gè)個(gè)上下文,三個(gè)上下文的代碼可以在一個(gè)部署單元里運(yùn)行,通過進(jìn)程內(nèi)調(diào)用來完成操作,這就是典型的單體架構(gòu);也可以各自在一個(gè)獨(dú)立的部署單元里運(yùn)行,通過遠(yuǎn)程調(diào)用來完成操作,這就是現(xiàn)在流行的微服務(wù)架構(gòu)。邊界清晰的好處
我們更多的是兩種架構(gòu)模式的一個(gè)混合,比如A和B一起是一個(gè)部署單元,C是另外一個(gè)獨(dú)立的部署單元,這種情況往往是因?yàn)镃非常重要,他并發(fā)的訪問量非常大,或者它的需求變更比較頻繁。將C拆分出來的有以下幾個(gè)好處:- 資源傾斜
- 使用彈力設(shè)計(jì)模式:比如重試,熔斷,降級(jí)
- 使用特殊技術(shù):比如Go語言
- 具備獨(dú)立代碼庫:有獨(dú)立團(tuán)隊(duì)和運(yùn)維人員,和A和B的運(yùn)行期做到隔離不互相影響
那么,為什么不把A和B都拆成一個(gè)獨(dú)立的部署單元?這會(huì)帶來更多的好處,也會(huì)帶來額外的成本,架構(gòu)應(yīng)該是可以演進(jìn)的,在業(yè)務(wù)發(fā)展的早期,應(yīng)該關(guān)注系統(tǒng)架構(gòu)的邏輯邊界,保持邏輯邊界的清晰和關(guān)系的正確,隨著業(yè)務(wù)量的增加,逐步在做拆分,這是組合應(yīng)用DDD和微服務(wù)架構(gòu)帶來的最大的好處。
在單體架構(gòu)中,保持架構(gòu)邏輯邊界不被突破是有一定難度。如果邏輯邊界不清晰,在需要服務(wù)器拆分的時(shí)候,就未必能拆得出來了。另外沒有人一下子就可以把邏輯邊界定義正確,即使這個(gè)上下文定義的不太正確,在DDD聚合根這個(gè)概念可以保障我們能夠演進(jìn)出更適合的上下文。
DDD界限上下文內(nèi)部通過實(shí)體和值對(duì)象來對(duì)領(lǐng)域概念進(jìn)行建模,一組實(shí)體和值子對(duì)象歸屬于一個(gè)聚合根。那按DDD要求:
- 聚合根用來保證內(nèi)部實(shí)體規(guī)則的正確性和數(shù)據(jù)的一致性
- 外部對(duì)象只能通過ID來引用聚合根,不能引用聚合根內(nèi)部的實(shí)體
- 聚合根之間不能共享一個(gè)數(shù)據(jù)庫事務(wù),它們之間的數(shù)據(jù)一致性需要通過最終的一致性來保障
特別推薦一個(gè)分享架構(gòu)+算法的優(yōu)質(zhì)內(nèi)容,還沒關(guān)注的小伙伴,可以長(zhǎng)按關(guān)注一下:
![]()
![]()
長(zhǎng)按訂閱更多精彩▼
![]()
如有收獲,點(diǎn)個(gè)在看,誠(chéng)摯感謝
免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。文章僅代表作者個(gè)人觀點(diǎn),不代表本平臺(tái)立場(chǎng),如有問題,請(qǐng)聯(lián)系我們,謝謝!