SpringCloud微服務(wù)開發(fā)實戰(zhàn):如何進(jìn)行微服務(wù)的拆分?
如何進(jìn)行微服務(wù)的拆分
在前面介紹了基于Spring Boot來快速實現(xiàn)一個“天氣預(yù)報”應(yīng)用。雖然沒有使用太多的代碼,但已經(jīng)實現(xiàn)了數(shù)據(jù)采集、數(shù)據(jù)緩存、提供天氣查詢等諸多的功能,這也是Spring Boot是快速實現(xiàn)企業(yè)級應(yīng)用開發(fā)的利器的原因。Spring Boot讓企業(yè)級應(yīng)用開發(fā)變得不再困難!
很顯然,這個“天氣預(yù)報”應(yīng)用是一個單塊架構(gòu)的應(yīng)用。它表面看上去很強(qiáng)大(集成了數(shù)據(jù)采集、數(shù)據(jù)緩存、提供天氣查詢等功能),但從另外一個角度看,它缺乏業(yè)務(wù)上的有效隔離。例如,如果第三方采集的接口協(xié)議變更怎么辦?緩存服務(wù)失效怎么辦?其中任何一個問題的發(fā)生,都勢必會影響整個應(yīng)用的可用性。
微服務(wù)拆分的意義
把所有雞蛋放在一個籃子里所帶來的風(fēng)險是顯而易見的——一損俱損。微服務(wù)架構(gòu)正是通過分而自治的理念來降低服務(wù)故障的風(fēng)險,從而實現(xiàn)服務(wù)的可行性。
1.微服務(wù)易于實現(xiàn)
更小的服務(wù)意味著更少的代碼。更小的服務(wù)意味著不必考慮太多整體的技術(shù)架構(gòu)或一站式的解決方案。只需要拿上趁手的兵器(開發(fā)工具和語言),奮勇開疆即可!
在實現(xiàn)微服務(wù)時,配以Spring Boot類開箱即用的工具,可以使自己更加有信心趕超進(jìn)度。
2.微服務(wù)易于維護(hù)
更小的服務(wù)意味著更少的代碼、更少的業(yè)務(wù)需求,也就容易被開發(fā)人員所理解,包括開發(fā)者和維護(hù)者。對于軟件設(shè)計來講,一個非常大的質(zhì)量指標(biāo),就是軟件是否可維護(hù)。更小、更內(nèi)聚的微服務(wù)更加易于維護(hù)。
3.微服務(wù)易于部署
微服務(wù)往往采用輕量級的技術(shù)來實現(xiàn),如內(nèi)嵌容器的方式,這樣,它更容易將其自身及所依賴的運行環(huán)境打成一個包來進(jìn)行分發(fā),從而避免了不同的部署導(dǎo)致的環(huán)境不一致的問題。再配合Docker等容器技術(shù),可以進(jìn)一步降低部署的復(fù)雜性。
4.微服務(wù)易于更新
微服務(wù)更容易被維護(hù)和修改,再加上每個微服務(wù)都是獨立部署的,這樣替換單個服務(wù),并不會影響整體的軟件功能。所以,微服務(wù)可以擁有對單塊架構(gòu)更加頻繁的更新頻率。
越頻繁地更新,意味著越早將用戶的需求反饋給用戶﹔用戶越早使用產(chǎn)品,越能發(fā)現(xiàn)程序的問題,這樣就能及早地提出變更需求,從而形成了一個如圖6-7所示的正向的反饋閉環(huán)。

拆分的原則
拆分微服務(wù)—般遵循如下原則。
1.單一職責(zé)原則
單一職責(zé)原則(Single Responsibility Principle,SRP)又稱單一功能原則,是面向?qū)ο蟮奈宕蠡驹瓌t(SOLID ) 之一。一個類只能有一個引起它變化的原因,因為它應(yīng)該只有一個職責(zé)。每一個職責(zé)都是變化的一個軸線,如果一個類有一個以上的職責(zé),這些職責(zé)就耦合在了一起。這會導(dǎo)致脆弱的設(shè)計。當(dāng)一個職責(zé)發(fā)生變化時,可能會影響其他的職責(zé)。另外,多個職責(zé)耦合在一起,會影響復(fù)用性。
在架構(gòu)設(shè)計中,業(yè)界普遍采用的是分層架構(gòu)。分層的原則之一就是每一層都是專注于自己所處的那一層的業(yè)務(wù)功能,即遵守單一職責(zé)的原則。劃分微服務(wù)時也要遵循單—職責(zé)原則,每個微服務(wù)只專注于解決一個業(yè)務(wù)功能。通過DDD的指導(dǎo),可以更加清楚地劃清不同業(yè)務(wù)之間的界限。
組織團(tuán)隊也要遵循單一職責(zé)原則,這樣才能很好地管理團(tuán)隊成員的時間,提高效率。一個人專注做一件事情的效率遠(yuǎn)高于同時關(guān)注多件事情。同樣一個人一直管理和維護(hù)同一份代碼要比多人同時維護(hù)多份代碼的效率高得多。這樣就能充分發(fā)揮每一個人的個性,專注于每個人所擅長的事,這樣做起事情來就會事半功倍,整個團(tuán)隊效率也會提高。
⒉.高內(nèi)聚
內(nèi)聚性又稱塊內(nèi)聯(lián)系,是指模塊功能強(qiáng)度的度量,即一個模塊內(nèi)部各個元素彼此結(jié)合的緊密程度的一種度量。若一個模塊內(nèi)各元素聯(lián)系得越緊密,則它的內(nèi)聚性就越高。
程序員希望把相關(guān)的行為都聚集在一起,把不相干的行為放到其他地方。這樣,當(dāng)他們要修改某個行為的時候,只需要在一個地方修改即可,然后就能對該修改及早地進(jìn)行發(fā)布。如果要在很多不同的地方做修改,那么就需要同時發(fā)布多個微服務(wù)才能交付這個功能。在多個不同的地方進(jìn)行修改會很慢,同時也引入了很多測試的工作量,而且部署多個服務(wù)的風(fēng)險也更加高。這兩者都是開發(fā)人員想要避免的。
所以,確定問題域的邊界,保證相關(guān)的行為能夠放置在相同的地方,并且確保它們與其他邊界以盡量低耦合的方式進(jìn)行通信。
3.低耦合
耦合性也稱塊間聯(lián)系,是指軟件系統(tǒng)結(jié)構(gòu)中各模塊間相互聯(lián)系緊密程度的一種度量。模塊之間聯(lián)系越緊密,其耦合性就越強(qiáng),模塊的獨立性則越差。模塊間耦合程度的高低取決于模塊間接口的復(fù)雜性、調(diào)用的方式及傳遞的信息。
能夠獨立地修改及部署單個服務(wù),而不需要修改系統(tǒng)的其他服務(wù)組成。
一個低耦合的服務(wù),應(yīng)盡可能少地了解其他服務(wù)的信息。這同時意味著,兩個服務(wù)之間需要限制不同調(diào)用形式的數(shù)量,因為除了潛在的性能問題以外,過度的通信往往是造成緊密耦合的“原罪”。
4.恰當(dāng)?shù)摹拔ⅰ?/span>
服務(wù)間的低耦合是指修改一個服務(wù),就不需要修改另一個服務(wù)。使用微服務(wù)最重要的一點就是,微服務(wù)到底多微才算“微”,這個業(yè)界也沒有一定的標(biāo)準(zhǔn)。微服務(wù)也不是越小越好。服務(wù)越小,微服務(wù)架構(gòu)的優(yōu)點和缺點也就會越來越明顯。服務(wù)越小,微服務(wù)的獨立性就會越高,但同時,微服務(wù)的數(shù)量也會激增,管理這些大批量的服務(wù)也將會是一個挑戰(zhàn)。所以服務(wù)的拆分也要考慮場景。例如,當(dāng)開發(fā)人員認(rèn)為自己的代碼庫過大時,往往就是拆分的最佳時機(jī)。代碼庫過大意味著業(yè)務(wù)過于復(fù)雜,明顯已經(jīng)超出了開發(fā)人員理解的范圍,所以也是需要考慮進(jìn)行拆分的。當(dāng)然,代碼庫的大小不能簡單地以代碼量來評價,畢竟復(fù)雜業(yè)務(wù)功能的代碼量,肯定比簡單業(yè)務(wù)的代碼量要高。同樣地,一個服務(wù),其功能本身的復(fù)雜性不同,代碼量也截然不同。
5.擁抱變化
好的系統(tǒng)架構(gòu)都不是一蹴而就的,而是通過不斷地完善、不斷地演進(jìn)而來。在構(gòu)建微服務(wù)架構(gòu)時也是如此,應(yīng)該是一個循序漸進(jìn)的過程,允許架構(gòu)在適當(dāng)?shù)臅r候做出調(diào)整,做出改變。在項目初始階段,團(tuán)隊的隊員之間肯定需要一個磨合,大家對于微服務(wù)的理解肯定也是各有差異,在構(gòu)建微服務(wù)的過程中,往往也會出現(xiàn)劃分服務(wù)不恰當(dāng)?shù)膯栴}。此時,最重要的是能夠容忍并改正錯誤,應(yīng)清醒地認(rèn)識到,錯誤是不可避免的,發(fā)現(xiàn)問題并努力去解決問題才是“王道”。在這之中,最關(guān)鍵的是團(tuán)隊要始終保持一個“擁抱變化”的心態(tài)。
拆分的方法
根據(jù)上面提到的拆分原則,拆分微服務(wù)主要有下面幾種方法。
1.橫向拆分
橫向拆分,即按照不同的業(yè)務(wù)功能,拆分成不同的微服務(wù),如天氣數(shù)據(jù)采集、數(shù)據(jù)存儲、天氣查詢等服務(wù),形成獨立的業(yè)務(wù)領(lǐng)域微服務(wù)集群,如圖6-8所示。

2.縱向拆分
縱向拆分,即把一個業(yè)務(wù)功能里的不同模塊或組件進(jìn)行拆分。例如,把公共組件拆分成獨立的基礎(chǔ)設(shè)施,下沉到底層,形成相對獨立的基礎(chǔ)設(shè)施層,如圖6-9所示。

圖6-9是一個縱向拆分的例子,其中各層次的職責(zé)如下。
用戶界面層(User Interface):也稱為用戶接口層或表示層(Presentation Layer),負(fù)責(zé)向用戶顯示信息或解釋用戶指令。這里的用戶可以是另外一個計算機(jī)系統(tǒng),而不一定是一個使用用戶界面的人。
應(yīng)用層(Application Layer):定義軟件要完成的任務(wù),并且指揮表達(dá)領(lǐng)域概念的對象來解決問題。該層主要負(fù)責(zé)的工作對于業(yè)務(wù)來說意義重大,也是與其他系統(tǒng)的應(yīng)用層進(jìn)行交互的必要渠道。應(yīng)用層應(yīng)該盡量簡單,不包括業(yè)務(wù)規(guī)則或只是為下一層中的領(lǐng)域?qū)ο髤f(xié)調(diào)任務(wù)、分配工作,使它們互相協(xié)作。它沒有反映業(yè)務(wù)情況的狀態(tài),但卻可以具有另外—種狀態(tài),為用戶或程序顯示某個進(jìn)度。
領(lǐng)域?qū)樱―omain Layer):或稱模型層(Model Layer),主要負(fù)責(zé)表達(dá)業(yè)務(wù)概念、業(yè)務(wù)狀態(tài)信息及業(yè)務(wù)規(guī)則。盡管保存業(yè)務(wù)狀態(tài)的技術(shù)細(xì)節(jié)是由基礎(chǔ)設(shè)施層實現(xiàn)的,但是反映業(yè)務(wù)情況的狀態(tài)是由本層控制并且使用的。領(lǐng)域?qū)邮菢I(yè)務(wù)軟件的核心。
基礎(chǔ)設(shè)施層(Infrastructure Layer):為上面各層提供通用的技術(shù)能力,如為應(yīng)用層傳遞消息、為領(lǐng)域?qū)犹峁?shù)據(jù)訪問及持久化機(jī)制、為用戶界面層繪制屏幕組件等。基礎(chǔ)設(shè)施層還能夠通過架構(gòu)框架來支持這4個層次間的交互。
3.使用DDD
一個微服務(wù),應(yīng)該能反映出某個業(yè)務(wù)的領(lǐng)域模型。使用DDD,不但可以減少微服務(wù)環(huán)境中通用語言的復(fù)雜性,而且可以幫助團(tuán)隊搞清楚領(lǐng)域的邊界,理清上下文邊界。
建議將每個微服務(wù)都設(shè)計成一個DDD限界上下文(Bounded Context)。這為系統(tǒng)內(nèi)的微服務(wù)提供了一個邏輯邊界,無論是在功能還是在通用語言上。每個獨立的團(tuán)隊負(fù)責(zé)一個邏輯上定義好的系統(tǒng)切片。最終,團(tuán)隊開發(fā)出的代碼會更易于理解和維護(hù)。
本篇文章給大家講的內(nèi)容是如何進(jìn)行微服務(wù)的拆分
下篇文章給大家講解領(lǐng)域驅(qū)動設(shè)計與業(yè)務(wù)建模;
覺得文章不錯的朋友可以轉(zhuǎn)發(fā)此文關(guān)注小編;
感謝大家的支持!!
本文就是愿天堂沒有BUG給大家分享的內(nèi)容,大家有收獲的話可以分享下,想學(xué)習(xí)更多的話可以到微信公眾號里找我,我等你哦。
