干貨速來!透徹剖析微服務(wù)架構(gòu)設(shè)計模式,深入開發(fā)Java有奇效
什么是微服務(wù)模式
隨著網(wǎng)絡(luò)基礎(chǔ)設(shè)施的高速發(fā)展,以及越來越多的個體接入互聯(lián)網(wǎng),在考慮構(gòu)建支持海量請求以及多變業(yè)務(wù)的軟件平臺時,微服務(wù)架構(gòu)成為多數(shù)人的首選。微服務(wù)架構(gòu)的出現(xiàn)時服務(wù)事物發(fā)展規(guī)律的:當(dāng)問題足夠大,有足夠多的的不確定因素時,人們習(xí)慣于把大的問題拆分成小的問題。通過分割,抽象和重用小而可靠的功能模塊來構(gòu)建整體方案。但是當(dāng)這些小的,可重用的部分多來越多的時候,又會出現(xiàn)新的問題。再相似的階段,人們遇到的問題也是相似的,這個時候人們需要一些共識,需要用一些通用的詞匯來描述問題以及解決方案,這也是人們知識的總結(jié),微服務(wù)模式就是這樣的總結(jié)和概括,是一種可以通用的共識,用于描述微服務(wù)領(lǐng)域的中的問題及解決方案。
Java架構(gòu)師入門到精通:?([Java進階資料])?點擊領(lǐng)取
單體結(jié)構(gòu)的歷程
在企業(yè)發(fā)展的初期,應(yīng)用程序相對較小,所有的代碼運行在一個應(yīng)用程序中有以下好處
不幸的是,開發(fā)人員已經(jīng)意識到的,單體架構(gòu)存在著巨大的局限性。每一次開發(fā)沖刺(), 開發(fā)團隊就會實現(xiàn)更多的功能,顯然這會導(dǎo)致代碼庫膨脹。而且,隨著公司的成功,研發(fā)團隊的規(guī)模不斷壯大。代碼庫規(guī)模變大的同時,團隊的管理成本也不斷提高。
Java架構(gòu)師入門到精通:?([Java進階資料])?點擊領(lǐng)取
過度的復(fù)雜性嚇退開發(fā)者
系統(tǒng)本身過于龐大和復(fù)雜,以至于任何一個開發(fā)者都很難理解它的全部。因此,修復(fù)軟件中的問題和正確地實現(xiàn)新功能就變得困難且耗時。各種交付截止時間都可能被錯過。更糟糕的是,這種極度的復(fù)雜性正在形成一個惡性循環(huán):由于代碼庫太難于理解,因此開發(fā)人員在更改時更容易出錯,每一次更改都會讓代碼庫變得更復(fù)雜、更難懂開發(fā)速度緩慢
巨大的項目把開發(fā)人員的 IDE 工具搞得很慢,構(gòu)建一次應(yīng)用需要很長時間,更要命的是,因為應(yīng)用太大,每啟動一次都需要很長的時間。因此,從編輯到構(gòu)建、運行再到測試這個周期花費的時間越來越長,這嚴重地影響了團隊的工作效率。從代碼提交到實際部署的周期很長,而且容易出問題
從代碼完成到運行在生產(chǎn)環(huán)境是一個漫長且費力的過程。一個問題是,眾多開發(fā)人員都向同一個代碼庫提交代碼更改,這常常使得這個代碼庫的構(gòu)建結(jié)果處于無法交付的狀態(tài)。當(dāng)我們嘗試采用功能分支來解決這個問題時,帶來的是漫長且痛苦的合并過程。緊接著,一旦團隊完成一個沖刺任務(wù),隨后迎接他們的將是一個漫長的測試和代碼穩(wěn)定周期。把更改推向生產(chǎn)環(huán)境的另一個挑戰(zhàn)是運行測試需要很長時間。因為代碼庫如此復(fù)雜,以至于一個更改可能引起的影響是未知的,為了避免牽一發(fā)而動全身的后果,即使是一個微小的更改,開發(fā)人員也必須在持續(xù)集成服務(wù)器上運行所有的測試套件。系統(tǒng)的某些部分甚至還需要手工測試。如果測試失敗,診斷和修復(fù)也需要更多的時間。因此,完成這樣的測試往往需要數(shù)天甚至更長時間。需要長期依賴某個可能已經(jīng)過時的技術(shù)棧
單體地獄的最終表現(xiàn),也體現(xiàn)在團隊必須長期使用一套相同的技術(shù)棧方面。單體架構(gòu)使得采用新的框架和編程語言變得極其困難。在單體應(yīng)用上采用新技術(shù)或者嘗試新技術(shù)都是極其昂貴和高風(fēng)險的,因為這個應(yīng)用必須被徹底重寫。結(jié)果就是,開發(fā)者被困在了他們一開始選擇的這個技術(shù)之內(nèi)。有時候這也就意味著團隊必須維護一個正在被廢棄或過時的技術(shù)所開發(fā)的應(yīng)用程序。
Java架構(gòu)師入門到精通:?([Java進階資料])?點擊領(lǐng)取
單體地獄的銀彈-微服務(wù)架構(gòu)
軟件架構(gòu)其實對功能性需求影響并不大。事實上,在任何架構(gòu)甚至是一團糟的架構(gòu)之上,你都可以實現(xiàn)一組用例(應(yīng)用的功能性需求)
架構(gòu)的重要性在于它影響了應(yīng)用的非功能性需求,也稱為質(zhì)量屬性或者其他的能力 。隨著 FTGO 應(yīng)用的增長,各種質(zhì)量屬性和問題都浮出水面,最顯著的就是影響軟件交付速度的可維護性、可擴展性和可測試性。 訓(xùn)練有素的團隊可以減緩項目陷入單體地獄的速度。團隊成員可以努力維護他們的模塊化應(yīng)用。他們也可以編寫全面的自動化測試。但是另一方面,他們無法避免大型團隊在單體應(yīng)用程序上協(xié)同工作的問題,也不能解決日益過時的技術(shù)棧問題。團隊所能做的就是延緩項目陷入單體地獄的速度,但這是不可避免的。為了逃避單體地獄,他們必須遷移到新架構(gòu):微服務(wù)架構(gòu)。
今天,針對大型復(fù)雜應(yīng)用的開發(fā),越來越多的共識趨向于考慮使用微服務(wù)架構(gòu)。但微服務(wù)到底是什么?不幸的是,微服務(wù)這個叫法本身暗示和強調(diào)了尺寸 。針對微服務(wù)架構(gòu)有多種定義。有些僅僅是在字面意義上做了定義:服務(wù)應(yīng)該是微小的不超過 100 行代碼,等等。另外有些定義要求服務(wù)的開發(fā)周期必須被限制在兩周之內(nèi)。曾在 工作的著名架構(gòu)師 把微服務(wù)架構(gòu)定義為面向服務(wù)的架構(gòu),它們由松耦合和具有邊界上下文的元素組成。這個定義不錯,但仍舊有些復(fù)雜難懂。立方體模型會是更好的定義。
擴展立方體和服務(wù)
Java架構(gòu)師入門到精通:?([Java進階資料])?點擊領(lǐng)取
X 軸擴展是擴展單體應(yīng)用程序的常用方法。在負載均衡器之后運行應(yīng)用程序的多個實例。負載均衡器在 N 個相同的實例之間分配請求。這是提高應(yīng)用程序吞吐量和可用性的好方法
服務(wù)本質(zhì)上是一個麻雀雖小但五臟俱全的應(yīng)用程序,它實現(xiàn)了一組相關(guān)的功能,例如訂單管理、客戶管理等。服務(wù)可以在需要的時候借助 X 軸或 Z 軸方式進行擴展。例如,訂單服務(wù)可以被部署為一組負載均衡的服務(wù)實例。
微服務(wù)架構(gòu)的概括性定義是:把應(yīng)用程序功能性分解為一組服務(wù)的架構(gòu)風(fēng)格。請注意這個定義中并沒有包含任何與規(guī)模有關(guān)的內(nèi)容。重要的是,每一個服務(wù)都是由一組專注的、內(nèi)聚的功能職責(zé)組成。
微服務(wù)架構(gòu)的好處和弊端優(yōu)點大型的復(fù)雜應(yīng)用程序可以持續(xù)交付和持續(xù)部署每個服務(wù)都相對較小并容易維護
微服務(wù)架構(gòu)的另一個好處在于:相比之下每個服務(wù)都比較小。開發(fā)者更容易理解服務(wù)中的代碼。較小規(guī)模的代碼庫不會把 IDE 等開發(fā)工具拖慢,這樣可以提升開發(fā)者的工作效率。服務(wù)的啟動速度也比大型的單體應(yīng)用快得多,千萬別小看這一點,快速啟動的服務(wù)會提高效率,加速研發(fā)(提高調(diào)試、部署等環(huán)節(jié)的效率)。
更好的容錯性
微服務(wù)架構(gòu)也可以實現(xiàn)更好的故障隔離。例如,某個服務(wù)中的內(nèi)存泄漏不會影響其他服務(wù)。其他服務(wù)仍舊可以正常地響應(yīng)請求。相比之下,單體架構(gòu)中的一個故障組件往往會拖垮整個系統(tǒng)
Java架構(gòu)師入門到精通:?([Java進階資料])?點擊領(lǐng)取
更容易實驗和采納新的技術(shù)
原則上,當(dāng)開發(fā)一個新的服務(wù)時,開發(fā)者可以自由選擇適用于這個服務(wù)的任何語言和框架。當(dāng)然,很多公司對此往往有各種限制和規(guī)范,但重要的是團隊有了選擇的權(quán)利,而不是被之前選定的技術(shù)綁架。更進一步,因為服務(wù)都相對比較小,使用更好的編程語言和技術(shù)來重寫一項服務(wù)變得有可能。這也意味著,如果對一項新技術(shù)的嘗試以失敗而告終,我們可以直接丟棄這部分工作而不至于給整個應(yīng)用帶來失敗的風(fēng)險。這跟單體架構(gòu)是完全不同的,單體架構(gòu)之下的技術(shù)選型會嚴重限制后期新技術(shù)的嘗試
當(dāng)然,沒有一項技術(shù)可以被稱為“銀彈” 。微服務(wù)架構(gòu)也存在一些顯著的弊端和問題
微服務(wù)架構(gòu)的主要弊端和問題如下:
服務(wù)的拆分和定義是一項挑戰(zhàn)
采用微服務(wù)架構(gòu)首當(dāng)其沖的問題,就是根本沒有一個具體的、良好定義的算法可以完成服務(wù)的拆分工作。與軟件開發(fā)一樣,服務(wù)的拆分和定義更像是一門藝術(shù)。更糟糕的是,如果對系統(tǒng)的服務(wù)拆分出現(xiàn)了偏差,你很有可能會構(gòu)建出一個分布式的單體應(yīng)用:一個包含了一大堆互相之間緊耦合的服務(wù),卻又必須部署在一起的所謂分布式系統(tǒng)。這將會把單體架構(gòu)和微服務(wù)架構(gòu)兩者的弊端集于一身。
分布式系統(tǒng)帶來的各種復(fù)雜性
使用微服務(wù)架構(gòu)的另一個問題是開發(fā)人員必須處理創(chuàng)建分布式系統(tǒng)的額外復(fù)雜性。服務(wù)必須使用進程間通信機制。這比簡單的方法調(diào)用更復(fù)雜。此外,必須設(shè)計服務(wù)來處理局部故障,并處理遠程服務(wù)不可用或出現(xiàn)高延遲的各種情況。
開發(fā)者需要思考到底應(yīng)該在應(yīng)用的什么階段使用微服務(wù)架構(gòu)
使用微服務(wù)架構(gòu)的另一個問題是決定在應(yīng)用程序生命周期的哪個階段開始使用這種架構(gòu)。在開發(fā)應(yīng)用程序的第一個版本時,你通常不會遇到需要微服務(wù)架構(gòu)才能解決的問題。此外,使用精心設(shè)計的分布式架構(gòu)將減緩開發(fā)速度。這對初創(chuàng)公司來說可能是得不償失的,其中最大的問題通常是在快速發(fā)展業(yè)務(wù)模型和維護一個優(yōu)雅的應(yīng)用架構(gòu)之間的取舍。微服務(wù)架構(gòu)使得項目開始階段的快速迭代變得非常困難。初創(chuàng)公司幾乎肯定應(yīng)該從單體的應(yīng)用程序開始 。但是稍后,當(dāng)問題變?yōu)槿绾翁幚韽?fù)雜性時,那就是將應(yīng)用程序功能性地分解為一組服務(wù)的時候了。由于盤根錯節(jié)的依賴關(guān)系,你會發(fā)現(xiàn)重構(gòu)很困難
服務(wù)的拆分策略
如何定義一個微服務(wù)架構(gòu)呢?跟所有的軟件開發(fā)過程一樣,一開始我們需要拿到領(lǐng)域?qū)<一蛘攥F(xiàn)有應(yīng)用的需求文檔。跟所有的軟件開發(fā)一樣,定義架構(gòu)也是一項藝術(shù)而非技術(shù)。本節(jié)我們將介紹一種定義應(yīng)用程序架構(gòu)的三步式流程
定義其架構(gòu)的第一步是將應(yīng)用程序的需求提煉為各種關(guān)鍵請求。但是,不是根據(jù)特定的進程間通信技術(shù)(如 REST 或消息)來描述這些請求,而是使用更抽象的系統(tǒng)操作這個概念。系統(tǒng)操作( )是應(yīng)用程序必須處理的請求的一種抽象描述。它既可以是更新數(shù)據(jù)的命令,也可以是檢索數(shù)據(jù)的查詢。每個命令的行為都是根據(jù)抽象領(lǐng)域模型定義的,抽象領(lǐng)域模型也是從需求中派生出來的。系統(tǒng)操作是描述服務(wù)之間協(xié)作方式的架構(gòu)場景
Java架構(gòu)師入門到精通:?([Java進階資料])?點擊領(lǐng)取
該流程的第二步是確定如何分解服務(wù)。有幾種策略可供選擇。一種源于業(yè)務(wù)架構(gòu)學(xué)派的策略是定義與業(yè)務(wù)能力相對應(yīng)的服務(wù)。另一種策略是圍繞領(lǐng)域驅(qū)動設(shè)計的子域來分解和設(shè)計服務(wù)。但這些策略的最終結(jié)果都是圍繞業(yè)務(wù)概念而非技術(shù)概念分解和設(shè)計的服務(wù)。
定義應(yīng)用程序架構(gòu)的第三步是確定每個服務(wù)的 API。為此,你將第一步中標(biāo)識的每個系統(tǒng)操作分配給服務(wù)。服務(wù)可以完全獨立地實現(xiàn)操作。或者,它可能需要與其他服務(wù)協(xié)作。在這種情況下,你可以確定服務(wù)的協(xié)作方式,這通常需要服務(wù)來支持其他操作
識別系統(tǒng)操作
定義應(yīng)用程序架構(gòu)的第一步是定義系統(tǒng)操作。起點是應(yīng)用程序的需求,包括用戶故事及其相關(guān)的用戶場景(請注意,這些與架構(gòu)場景不同)。使用圖 2-6 中所示的兩步式流程識別和定義系統(tǒng)操作。第一步創(chuàng)建由關(guān)鍵類組成的抽象領(lǐng)域模型,這些關(guān)鍵類提供用于描述系統(tǒng)操作的詞匯表。第二步確定系統(tǒng)操作,并根據(jù)領(lǐng)域模型描述每個系統(tǒng)操作的行為。
創(chuàng)建抽象領(lǐng)域模型
定義系統(tǒng)操作的第一步是為這個應(yīng)用程序描繪一個抽象的領(lǐng)域模型。注意這個模型比我們最終要實現(xiàn)的簡單很多。應(yīng)用程序本身并不需要一個領(lǐng)域模型,因為我們在稍后會學(xué)到,每一個服務(wù)都有它自己的領(lǐng)域模型。盡管非常簡單,抽象的領(lǐng)域模型仍舊有助于在開始階段提供幫助,因為它定義了描述系統(tǒng)操作行為的一些詞語
創(chuàng)建領(lǐng)域模型會采用一些標(biāo)準(zhǔn)的技術(shù),例如通過與領(lǐng)域?qū)<覝贤ê螅治鲇脩艄适潞蛨鼍爸蓄l繁出現(xiàn)的名詞。例如 Place Order 用戶故事微課程設(shè)計的點鏈圈 plc 模型研究,我們可以把它分解為多個用戶場景,
Given a consumer
And a restaurantAnd a delivery address/time that can be served by that restaurantAnd an order total that meets the restaurant's order minimum
When the consumer places an order for the restaurant
Then consumer's credit card is authorized
And an order is created in the PENDING_ACCEPTANCE state
And the order is associated with the consumer
And the order is associated with the restaurant
在這個用戶場景中的名詞,如 、Order、 和 ,暗示了這些類都是需要的
同樣, Order 用戶故事也可以分解為多個場景,如下
Given an order that is in the PENDING_ACCEPTANCE state
and a courier that is available to deliver the orderWhen a restaurant accepts an order with a promise to prepare by a particular
timeThen the state of the order is changed to ACCEPTED
And the order's promiseByTime is updated to the promised time
And the courier is assigned to deliver the order
經(jīng)過分析最終我們可以得出如下的類圖結(jié)構(gòu)
每一個類的作用如下:
定義系統(tǒng)操作
當(dāng)定義了抽象的領(lǐng)域模型之后,接下來就要識別系統(tǒng)必須處理的各種請求。我們并不討論具體的用戶界面,但是你能夠想象在每一個用戶場景下,前端的用戶界面向后端的業(yè)務(wù)邏輯發(fā)出請求,后端的業(yè)務(wù)邏輯進行數(shù)據(jù)的獲取和處理
識別系統(tǒng)指令的切入點是分析用戶故事和場景中的動詞。例如 Place Order 用戶故事,它非常明確地告訴我們,這個系統(tǒng)必須提供一個 Order 操作。很多用戶故事都會直接對應(yīng)或映射為系統(tǒng)命令。表 2-1 列出了一些關(guān)鍵的系統(tǒng)命令
Java架構(gòu)師入門到精通:?([Java進階資料])?點擊領(lǐng)取
命令規(guī)范定義了命令對應(yīng)的參數(shù)、返回值和領(lǐng)域模型類的行為。行為規(guī)范中包括前置條件(即當(dāng)這個操作被調(diào)用時必須滿足的條件)和后置條件(即這個操作被調(diào)用后必須滿足的條件)。例如,以下就是 () 系統(tǒng)操作的規(guī)范。
前置條件對應(yīng)著 Place Order 用戶場景中的 ,后置條件對應(yīng)著場景中的Then。當(dāng)系統(tǒng)操作被調(diào)用時,它會檢查前置條件,執(zhí)行操作來完成和滿足后置條件。
抽象的領(lǐng)域模型和系統(tǒng)操作能夠回答這個應(yīng)用“做什么”這一問題。這有助于推動應(yīng)用程序的架構(gòu)設(shè)計。每一個系統(tǒng)操作的行為都通過領(lǐng)域模型的方式來描述。每一個重要的系統(tǒng)操作都對應(yīng)著架構(gòu)層面的一個重大場景,是架構(gòu)中需要詳細描述和特別考慮的地方。現(xiàn)在我們來看看如何定義應(yīng)用程序的微服務(wù)架構(gòu)
系統(tǒng)操作被定義后,下一步就是完成應(yīng)用服務(wù)的識別。如之前提到的,這并不是一個機械化的流程,相反,有多種拆分策略可供選擇。每一種都是從一個側(cè)面來解決問題,并且使用它們獨有的一些術(shù)語。但是殊途同歸,這些策略的結(jié)果都是一樣的:一個包含若干服務(wù)的架構(gòu),這樣的架構(gòu)是以業(yè)務(wù)而不是技術(shù)概念為中心
根據(jù)業(yè)務(wù)能力進行服務(wù)拆分
創(chuàng)建微服務(wù)架構(gòu)的策略之一就是采用業(yè)務(wù)能力進行服務(wù)拆分。業(yè)務(wù)能力是一個來自于業(yè)務(wù)架構(gòu)建模的術(shù)語。業(yè)務(wù)能力是指一些能夠為公司(或組織)產(chǎn)生價值的商業(yè)活動。特定業(yè)務(wù)的業(yè)務(wù)能力取決于這個業(yè)務(wù)的類型。例如,保險公司業(yè)務(wù)能力通常包括承保、理賠管理、賬務(wù)和合規(guī)等。在線商店的業(yè)務(wù)能力包括:訂單管理、庫存管理和發(fā)貨
組織的業(yè)務(wù)能力通常是指這個組織的業(yè)務(wù)是做什么,它們通常都是穩(wěn)定的。與之相反,組織采用何種方式來實現(xiàn)它的業(yè)務(wù)能力,是隨著時間不斷變化的。這個準(zhǔn)則在今天尤其明顯,很多新技術(shù)在被快速采用,商業(yè)流程的自動化程度越來越高。例如,不久之前你還通過把支票交給銀行柜員的方式來兌現(xiàn)支票,現(xiàn)在很多 ATM 機都支持直接兌現(xiàn)支票,而今,人們甚至可以使用智能手機拍照的方式來兌現(xiàn)支票。正如你所見,“兌現(xiàn)支票”這個業(yè)務(wù)能力是穩(wěn)定不變的,但是這個能力的實現(xiàn)方式正在發(fā)生戲劇性的變化
從業(yè)務(wù)能力到服務(wù)
一旦確定了業(yè)務(wù)能力,就可以為每個能力或相關(guān)能力組定義服務(wù)。下圖顯示了 FTGO應(yīng)用程序從能力到服務(wù)的映射。某些頂級能力(如會計記賬能力)將映射到服務(wù)。在其他情況下,子能力映射到服務(wù)
上圖顯示的服務(wù)僅僅是定義架構(gòu)的第一次嘗試。隨著我們對應(yīng)用程序領(lǐng)域的了解越來越多,它們可能會隨著時間的推移而變化,特別是架構(gòu)定義流程中的一個重要步驟是調(diào)查服務(wù)如何在每個關(guān)鍵架構(gòu)服務(wù)中協(xié)作。例如,你可能會發(fā)現(xiàn)由于過多的進程間通信而導(dǎo)致特定的分解效率低下,導(dǎo)致你必須把一些服務(wù)組合在一起。相反,服務(wù)可能會在復(fù)雜性方面增長到值得將其拆分為多個服務(wù)的程度
根據(jù)子域進行服務(wù)拆分
領(lǐng)域驅(qū)動設(shè)計是構(gòu)建復(fù)雜軟件的方法論,這些軟件通常都以面向?qū)ο蠛皖I(lǐng)域模型為核心。領(lǐng)域模型以解決具體問題的方式包含了一個領(lǐng)域內(nèi)的知識。它定義了當(dāng)前領(lǐng)域相關(guān)團隊的詞匯表,DDD 也稱之為通用語言( )。領(lǐng)域模型會被緊密地映射到應(yīng)用的設(shè)計和實現(xiàn)環(huán)節(jié)。在微服務(wù)架構(gòu)的設(shè)計層面,DDD 有兩個特別重要的概念,子域和限界上下文
領(lǐng)域驅(qū)動為每一個子域定義單獨的領(lǐng)域模型。子域是領(lǐng)域的一部分,領(lǐng)域是 DDD 中用來描述應(yīng)用程序問題域的一個術(shù)語。識別子域的方式跟識別業(yè)務(wù)能力一樣:分析業(yè)務(wù)并識別業(yè)務(wù)的不同專業(yè)領(lǐng)域,分析產(chǎn)出的子域定義結(jié)果也會跟業(yè)務(wù)能力非常接近。FTGO 的子域包括:訂單獲取、訂單管理、餐館管理、送餐和會計。正如你所見:這些子域跟我們之前定義的業(yè)務(wù)能力非常接近。
DDD 把領(lǐng)域模型的邊界稱為限界上下文( )。限界上下文包括實現(xiàn)這個模型的代碼集合。當(dāng)使用微服務(wù)架構(gòu)時,每一個限界上下文對應(yīng)一個或者一組服務(wù)。換一種說法,我們可以通過 DDD 的方式定義子域,并把子域?qū)?yīng)為每一個服務(wù),這樣就完成了微服務(wù)架構(gòu)的設(shè)計工作。圖 2-9 展示了子域和服務(wù)之間的映射,每一個子域都有屬于它們自己的領(lǐng)域模型。
DDD 和微服務(wù)架構(gòu)簡直就是天生一對。DDD 的子域和限界上下文的概念,可以很好地跟微服務(wù)架構(gòu)中的服務(wù)進行匹配。而且,微服務(wù)架構(gòu)中的自治化團隊負責(zé)服務(wù)開發(fā)的概念,也跟 DDD 中每個領(lǐng)域模型都由一個獨立團隊負責(zé)開發(fā)的概念吻合。更有趣的是,子域用于它自己的領(lǐng)域模型這個概念,為消除上帝類和優(yōu)化服務(wù)拆分提供了好辦法
上帝類的處理
上帝類是在整個應(yīng)用程序中使用的全局類。上帝類通常為應(yīng)用程序的許多不同方面實現(xiàn)業(yè)務(wù)邏輯。它有大量字段映射到具有許多列的數(shù)據(jù)庫表。大多數(shù)應(yīng)用程序至少有一個這樣的上帝類。Order 類是 FTGO 應(yīng)用程序中上帝類的一個很好的例子。這并不奇怪:畢竟 FTGO 的
目的是向客戶提供食品訂單。系統(tǒng)的大多數(shù)部分都涉及訂單。如果 FTGO 應(yīng)用程序具有單個領(lǐng)域模型,則 Order 類將是一個非常大的類。它將具有與應(yīng)用程序的許多不同部分相對應(yīng)的狀態(tài)和行為。下圖顯示了使用傳統(tǒng)建模技術(shù)創(chuàng)建的 Order 類的結(jié)構(gòu)
Order 類具有與訂單處理、餐館訂單管理、送餐和付款相對應(yīng)的字段及方法。由于一個模型必須描述來自應(yīng)用程序的不同部分的狀態(tài)轉(zhuǎn)換,因此該類還具有復(fù)雜的狀態(tài)模型。在目前情況下,這個類的存在使得將代碼分割成服務(wù)變得極其困難
一種解決方案是將 Order 類打包到庫中并創(chuàng)建一個中央 Order 數(shù)據(jù)庫。處理訂單的所有服務(wù)都使用此庫并訪問訪問數(shù)據(jù)庫。這種方法的問題在于它違反了微服務(wù)架構(gòu)的一個關(guān)鍵原則,并導(dǎo)致我們特別不愿意看到的緊耦合。例如,對 Order 模式的任何更改都要求其他開發(fā)團隊同步更新和重新編譯他們的代碼。
另一種解決方案是將 Order 數(shù)據(jù)庫封裝在 Order 中,該服務(wù)由其他服務(wù)調(diào)用以檢索和更新訂單。該設(shè)計的問題在于這樣的一個 Order 將成為一個純數(shù)據(jù)服務(wù),成為包含很少或沒有業(yè)務(wù)邏輯的貧血領(lǐng)域模型( model)。這兩種解決方案都沒有吸引力,但幸運的是,DDD 提供了一個好的解決方案。
更好的方法是應(yīng)用 DDD 并將每個服務(wù)視為具有自己的領(lǐng)域模型的單獨子域。這意味著FTGO 應(yīng)用程序中與訂單有關(guān)的每個服務(wù)都有自己的領(lǐng)域模型及其對應(yīng)的 Order 類的版本。 是多領(lǐng)域模型的一個很好的例子。如圖 2-11 所示為 Order,它非常簡單:取餐地址、取餐時間、送餐地址和送餐時間。此外, 使用更合適的 名稱,而不是稱之為 Order。 對訂單的任何其他屬性不感興趣
有一個更簡單的訂單視圖。它的 Order 版本就是一個 (后 廚 工 單)。如圖所 示, 只包含 、e、 以及告訴餐館準(zhǔn)備的訂單項列表。它不關(guān)心消費者、付款、交付等這些與它無關(guān)的事情
Order 具有最復(fù)雜的訂單視圖,如圖所示。即使它有相當(dāng)多的字段和方法,它仍然比原始版本的那個 Order 上帝類簡單得多。
每個領(lǐng)域模型中的 Order 類表示同一 Order 業(yè)務(wù)實體的不同方面。FTGO 應(yīng)用程序必須維持不同服務(wù)中這些不同對象之間的一致性。例如,一旦 Order 授權(quán)消費者的信用卡微課程設(shè)計的點鏈圈 plc 模型研究,它必須觸發(fā)在 中創(chuàng)建 。同樣,如果 拒絕訂單,則必須在 Order 中取消訂單,并且為客戶退款。我們通常會用用分布式事務(wù)去處理這些問題,這又是微服務(wù)架構(gòu)的另一個問題了。
以上就是小編整理的微服務(wù)架構(gòu)設(shè)計模式,有哪里不準(zhǔn)確的,請各位朋友多多指出,小編和大家一起共同學(xué)習(xí)進步~~~
Java架構(gòu)師入門到精通:?([Java進階資料])?點擊領(lǐng)取