關(guān)鍵要點(diǎn):
微服務(wù)架構(gòu)將應(yīng)用功能分解為多個(gè)服務(wù),其中每個(gè)服務(wù)都對(duì)應(yīng)于一種業(yè)務(wù)能力。
開發(fā)基于微服務(wù)的業(yè)務(wù)應(yīng)用時(shí),一個(gè)主要挑戰(zhàn)是功能分解在事務(wù)、領(lǐng)域模型和查詢中受到了抵制。
領(lǐng)域模型可分解為多個(gè)領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)(Domain Driven Design,DDD)聚合。
每個(gè)服務(wù)的業(yè)務(wù)邏輯都是一個(gè)領(lǐng)域模型,該領(lǐng)域模型由一個(gè)或更多的DDD聚合所組成。
在服務(wù)中,每個(gè)事務(wù)只對(duì)單一的聚合進(jìn)行創(chuàng)建或更新。
事件用于維持聚合間(服務(wù)間)的一致性。
微服務(wù)架構(gòu) 正變得越來越流行。作為一種實(shí)現(xiàn)模塊化的方法,微服務(wù)架構(gòu)將應(yīng)用功能分解為一組服務(wù)。團(tuán)隊(duì)可使用微服務(wù)架構(gòu)去開發(fā)大型復(fù)雜的應(yīng)用,這樣可以更塊地交付更好的軟件。微服務(wù)架構(gòu)還使得在開發(fā)中更易于采用新的技術(shù),因?yàn)閳F(tuán)隊(duì)可使用最新最適合的技術(shù)棧去對(duì)每個(gè)服務(wù)進(jìn)行實(shí)現(xiàn)。此外,通過使每個(gè)服務(wù)都可以部署在最優(yōu)的硬件上,微服務(wù)架構(gòu)可改進(jìn)應(yīng)用的可擴(kuò)展性。
但是微服務(wù)并非是一劑良方。尤其是在領(lǐng)域模型、事務(wù)和查詢中,功能分解受到了出乎意料地抵制。由于這個(gè)問題的存在,使用微服務(wù)架構(gòu)開發(fā)事務(wù)性業(yè)務(wù)應(yīng)用是一件具有挑戰(zhàn)性的事情。在本文中,我將給出了一種微服務(wù)開發(fā)的方法,該方法使用領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)、事件溯源和命令查詢職責(zé)分離(Command Query Responsibility Segregation,CQRS)技術(shù)解決了上述的問題。讓我們首先看一下開發(fā)人員在編寫微服務(wù)中所面對(duì)的挑戰(zhàn)。
微服務(wù)開發(fā)中的挑戰(zhàn)
在大型復(fù)雜應(yīng)用的開發(fā)中,模塊化是至關(guān)重要的。大多數(shù)現(xiàn)代應(yīng)用的規(guī)模決定了它不可能由單個(gè)開發(fā)人員單槍匹馬地開發(fā)實(shí)現(xiàn),這些應(yīng)用的復(fù)雜度也不可能被單個(gè)開發(fā)人員所理解。這樣應(yīng)用必須要被分解為模塊,而模塊是可被已形成團(tuán)隊(duì)的開發(fā)人員理解并開發(fā)實(shí)現(xiàn)的。在整體應(yīng)用程序中,可使用諸如Java包這樣的編程語言結(jié)構(gòu)定義模塊。但這種方法常常在實(shí)踐中并不好用。長(zhǎng)生命周期的 整體應(yīng)用程序 通常會(huì)退化為一個(gè)“大泥球”(譯者注:指一個(gè)微服務(wù)中的問題將會(huì)擴(kuò)展到整個(gè)應(yīng)用中)。
微服務(wù)架構(gòu)使用服務(wù)作為模塊化單元。每個(gè)服務(wù)對(duì)應(yīng)于一種業(yè)務(wù)能力,即企業(yè)為創(chuàng)造價(jià)值所執(zhí)行的操作。這里以一個(gè)基于微服務(wù)的網(wǎng)店為例。該網(wǎng)店由各種服務(wù)所組成,其中包括訂單服務(wù)(Order Service)、客戶服務(wù)(Customer Service)和商品目錄服務(wù)(Catalog Service)。

每個(gè)服務(wù)都具有難以違反的防滲透邊界。正是由于該原因,應(yīng)用的模塊化的保持是經(jīng)得起時(shí)間考驗(yàn)的。微服務(wù)架構(gòu)的其它優(yōu)點(diǎn)還包括可獨(dú)立地部署和擴(kuò)展服務(wù)的能力。
遺憾的是,將應(yīng)用分解為服務(wù)實(shí)現(xiàn)起來并非聽上去那么容易。應(yīng)用中有很多不同的方面是難以被分解的,這包括了領(lǐng)域模型、事務(wù)和查詢。下面讓我們看一下為什么會(huì)這樣。
問題一:分解領(lǐng)域模型
領(lǐng)域模型模式 是一種實(shí)現(xiàn)復(fù)雜業(yè)務(wù)邏輯的好方法。網(wǎng)店的領(lǐng)域模型可包括Order(訂單)類、OrderLineItem(訂單條目)類、Customer(客戶)類和Product(商品)類等。在微服務(wù)架構(gòu)中,Order類和OrderLineItem類是訂單服務(wù)的一部分,Customer類是客戶服務(wù)的一部分,而Product類屬于商品目錄服務(wù)。

然而,分解領(lǐng)域模型的挑戰(zhàn)性在于各個(gè)類之間的相互引用。例如,Order類會(huì)引用其Customer類,OrderLineItem類引用Product類。該如何去處理這些跨越了服務(wù)邊界的引用關(guān)系呢?在本文后面的內(nèi)容中,讀者將讀到如何使用源于領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)的聚合概念去解決這個(gè)問題。
微服務(wù)和數(shù)據(jù)庫
微服務(wù)的一個(gè)特有特性是,服務(wù)所擁有的數(shù)據(jù)只能通過該服務(wù)提供的API訪問?;氐骄W(wǎng)店的例子上,訂單服務(wù)的數(shù)據(jù)庫中有一個(gè)ORDERS表,客戶服務(wù)的數(shù)據(jù)庫中有一個(gè)CUSTOMERS表。這種封裝表明服務(wù)是松耦合的。在開發(fā)時(shí),訂單服務(wù)和客戶服務(wù)的開發(fā)人員無需與其它服務(wù)的開發(fā)者進(jìn)行協(xié)調(diào),就可以去改變這兩個(gè)服務(wù)的服務(wù)模式。在運(yùn)行時(shí)服務(wù)之間是相互獨(dú)立。例如,一個(gè)服務(wù)將永遠(yuǎn)不會(huì)因?yàn)榈却渌?wù)所擁有的數(shù)據(jù)庫鎖而被阻塞。遺憾的是,該數(shù)據(jù)庫按功能的分解導(dǎo)致了數(shù)據(jù)一致性難于維持,還導(dǎo)致一些類型的查詢難于實(shí)現(xiàn)。