微服務的設計模式

瞭解微服務架構的設計模式以克服採用它所帶來的挑戰。

微服務架構已經成爲現代應用程序開發中公認的技術選擇。儘管它解決了某些問題,但不是靈丹妙藥。它有幾個缺點,使用這種體系架構時,還需要解決許多問題。這就需要學習這些問題的通用模式,並通過可重用的解決方案來解決它們。因此,有必要討論微服務的設計模式。在深入研究設計模式之前,我們需要了解微服務架構的構建原理:
1.可擴展性
2.可用性
3.彈性
4.獨立自治性
5.去中心化治理
6.失敗隔離
7.自動配置
8.通過DevOps持續交付

應用所有這些原則會帶來一些挑戰和問題。讓我們討論這些問題及其解決方案。


分解模式#

按業務能力分解#

問題#

微服務就是要應用單一責任原則使服務鬆散耦合。但是,將應用程序分成較小的部分必須在邏輯上完成。那麼,我們如何將應用程序分解爲小型服務呢?

解決#

一種策略是按業務能力分解。所謂業務能力就是可以體現企業業務價值的,給定業務的功能集取決於業務類型。例如,保險公司的功能通常包括銷售,市場營銷,承保,理賠處理,計費,合規性等。每個業務功能都可以視爲一種服務,但它是面向業務的,而不是技術的。

按子域分解#

問題#

使用業務功能分解應用程序可能是一個不錯的開始,但是您會遇到所謂的“神類”,這些類將不容易分解。它們將在多種服務中通用。例如,訂單類將用於“訂單管理”,“接單”,“訂單交付”等業務中。我們該如何分解它們?

解決#

對於“神類”問題,DDD(領域驅動設計)可以解決。它使用子域和有界上下文概念來解決此問題。DDD將爲企業創建的整個域模型分解爲子域。每個子域都有一個模型,該模型的範圍稱爲有界上下文。每個微服務將圍繞有界的上下文進行開發。
注意:確定子域並非易事。它需要對業務的瞭解。像業務功能一樣,通過分析業務及其組織結構並確定不同的專業領域來標識子域。

扼殺模式#

問題#

到目前爲止,我們討論的設計模式都是分解未開發的應用程序,但是我們所做的工作中有80%是用於棕色的應用程序,這是大型的整體應用程序。將上述所有設計模式應用於它們將很困難,因爲把他們當作一個整體應用的同時將它們拆分成一個個較小的部分是一項艱鉅的任務。

解決#

扼殺者模式可以解決此類問題。扼殺者模式是基於藤蔓纏繞植物的類比。此解決方案與Web應用程序配合使用,在Web應用程序之間來回調用,對於每個URI調用,服務可以分爲不同的域並作爲單獨的服務託管。這個想法是一次做一個域。這將創建兩個單獨的應用程序,它們在同一URI空間中並排運行。最終,新重構的應用程序會“扼殺”或替換原始應用程序,直到最終您可以關閉整體應用程序。

整合模式#

api網關#

問題#

當一個應用被分解爲多個微服務時,還會有一些問題需要解決。

1.如何調用多個微服務來抽象生產者信息。

2.在不同的渠道(例如臺式機,移動設備和平板電腦)上,由於UI可能不同,應用程序需要不同的數據來響應相同的後端服務。

3.不同的使用者對於可重複使用的微服務響應格式可能不同。誰將進行數據轉換或現場操作?

4.生產者微服務可能不支持某些類型協議的處理方式。

解決#

API網關有助於解決微服務實現引起的許多問題,而不僅限於上述問題。

1.API網關是任何微服務調用的單一入口點。

2.它可以用作代理服務,以將請求路由到相關的微服務,從而抽象出生產者詳細信息。

3.它可以將對多個服務的請求散發出去,然後彙總結果以發送回消費者。

4.千篇一律的所有API不能解決所有消費者的需求;該解決方案可以爲每種特定類型的客戶端創建一個細粒度的API。

5.它還可以將協議請求(例如AMQP)轉換爲另一個協議(例如HTTP),反之亦然,以便生產者和消費者可以處理它。

6.它還可以減輕微服務的身份驗證/授權責任。

聚合器#

問題#

我們已經討論瞭解決API網關模式中的聚合數據問題。但是,我們將在這裏全面討論它。
將業務功能分解爲幾個較小的邏輯代碼段時,有必要考慮如何聚合每個服務返回的數據。消費者不能承擔此責任,因爲這可能需要了解生產者應用程序的內部實現。

解決#

聚集器模式有助於解決此問題。它討論瞭如何聚合來自不同服務的數據,然後將最終響應發送給消費者。這可以通過兩種方式完成:

1.複合微服務將調用所有必需的微服務,合併數據,並在發送回數據之前對其進行轉換。

2.API網關還可以將請求劃分爲多個微服務並聚合數據,然後再將其發送給使用者。

如果要應用任何業務邏輯,建議選擇複合微服務。否則,API網關是已建立的解決方案。

客戶端UI組合#

問題#

通過分解業務功能/子域來開發服務時,負責用戶體驗的服務必須從多個微服務中提取數據。在整體應用中,從UI到後端服務只有一次調用,以檢索所有數據並刷新/提交UI頁面。但是,現在不一樣了。我們需要了解如何去做。

解決#

對於微服務,必須將UI設計爲具有屏幕/頁面的多個部分/區域的框架。每個部分都將調用單個後端微服務以提取數據。這稱爲組成特定於服務的UI組件。諸如AngularJS和ReactJS之類的框架可以輕鬆地做到這一點。這些屏幕稱爲單頁應用程序(SPA)。這使應用程序可以刷新屏幕的特定區域而不是刷新整個頁面。

數據庫模式#

每個服務一個數據庫#

問題#

如何定義微服務的數據庫體系結構存在一個問題。以下是要解決的問題:

1.服務必須鬆散耦合。它們可以獨立開發,部署和擴展。

2.業務事務可能會強制跨越多個服務的不變量。

3.一些業務事務需要查詢多個服務擁有的數據。

4.有時必須複製數據庫並對其進行分片以進行擴展。

5.不同的服務具有不同的數據存儲要求。

解決#

爲了解決上述問題,必須爲每個微服務設計一個數據庫。它必須僅對該服務專用。只能由微服務API訪問它。其他服務無法直接訪問它。例如,對於關係數據庫,我們可以使用每個服務一個專用表,每個服務一個schema或每個服務一個數據庫服務器。每個微服務應具有一個單獨的數據庫ID,以便可以給予單獨的訪問權限以設置障礙並防止其使用其他服務表。

每個服務共享數據庫#

問題#

我們已經討論了每個服務一個數據庫是微服務的理想選擇,當應用程序是未開發的並且要使用DDD開發時,這是可能的。但是,如果應用程序是一個整體並且試圖闖入微服務,那麼非規範化就不那麼容易了。在那種情況下合適的架構是什麼?

解決#

每個服務共享數據庫不是理想的選擇,但這是上述情況的可行解決方案。大多數人認爲這是微服務的反模式,但對於棕色應用程序來說,這是將應用程序分解成較小邏輯部分的一個很好的開始。這不適用於未開發的應用程序。在這種模式下,一個數據庫可以與一個以上的微服務對齊,但是必須限制爲最大2-3個微服務,否則伸縮,自治和獨立性將難以執行。

命令查詢職責隔離(CQRS)#

問題#

一旦我們實現了每個服務的數據庫,就需要進行查詢,這需要來自多個服務的聯合數據-這是不可能的。那麼,我們如何在微服務架構中實現查詢?

解決#

CQRS建議將應用程序分爲兩部分-命令端和查詢端。命令行處理創建,更新和刪除請求。查詢端通過使用實例化視圖來處理查詢部分。通常將事件源模式與它一起使用來爲任何數據更改創建事件。通過訂閱事件流,可以使實例化視圖保持更新。

saga模式#

問題#

當每個服務都有自己的數據庫並且一個業務事務跨越多個服務時,我們如何確保各個服務之間的數據一致性?例如,對於客戶有信用額度的電子商務應用程序,該應用程序必須確保新訂單不會超過客戶的信用額度。由於訂單和客戶位於不同的數據庫中,因此應用程序不能簡單地使用本地ACID事務。

解決#

Saga代表由幾個子請求組成的高級業務流程,每個子請求在單個服務中更新數據。每個請求都有一個補償請求,該請求在請求失敗時執行。它可以通過兩種方式實現:

1.Choreography-如果沒有中央協調,則每個服務都會產生並偵聽另一個服務的事件,並決定是否應採取措施。
2.Orchestration-協調員(對象)負責傳奇的決策和業務邏輯排序。

可觀察性模式#

日誌彙總#

問題#

考慮一個用例,其中一個應用程序由在多臺計算機上運行的多個服務實例組成。請求通常跨越多個服務實例。每個服務實例均以標準化格式生成日誌文件。我們如何通過日誌瞭解特定請求的應用程序行爲?

解決#

我們需要一個集中式日誌記錄服務,該服務可以彙總每個服務實例的日誌。用戶可以搜索和分析日誌。他們可以配置在某些消息出現在日誌中時觸發的警報。例如,PCF確實具有Loggeregator,它從PCF平臺的每個組件(路由器,控制器,diego等)收集日誌,並附帶應用程序。 AWS Cloud Watch也這樣做。

性能指標#

問題#

當服務組合由於微服務架構而增加時,密切關注事務至關重要,以便可以監控模式並在發生問題時發送警報。我們應該如何收集指標以監視應用程序性能?

解決#

需要度量服務來收集有關單個操作的統計信息。它應該聚合提供報告和警報的應用程序服務的指標。有兩種用於彙總指標的模型:

1.推送-服務將指標推送到指標服務,例如NewRelic,AppDynamics

2.提取-指標服務從服務中提取指標,例如普羅米修斯

分佈式跟蹤#

問題#

在微服務架構中,請求通常跨越多個服務。每個服務通過跨多個服務執行一個或多個操作來處​​理請求。然後,我們如何跟蹤端到端的請求以解決問題?

解決#

我們需要一項服務

爲每個外部請求分配一個唯一的外部請求ID。

將外部請求ID傳遞給所有服務。

在所有日誌消息中包括外部請求ID。

記錄有關請求和在集中式服務中處理外部請求時執行的操作的信息(例如開始時間,結束時間)。

Spring Cloud Slueth與Zipkin服務器一起是常見的實現。

健康檢查#

問題#

實施微服務架構後,服務可能會啓動但無法處理事務。在這種情況下,如何確保請求不會發送到那些失敗的實例?用負載均衡模式實現。

解決#

每個服務都需要有一個端點,可用於檢查應用程序的運行狀況,例如/health。該API應該可以檢查主機的狀態,與其他服務/基礎結構的連接以及任何特定的邏輯。
Spring Boot Actuator確實實現了/health端點,並且該實現也可以自定義。

Cross-Cutting Concern(橫切關注)模式#

外部配置#

問題#

服務通常還會調用其他服務和數據庫。對於開發,質量檢查,UAT,產品等每個環境,端點URL或某如些配置屬性可能會有所不同。這些屬性中的任何一個更改都可能需要重新構建和重新部署服務。我們何避免對配置更改進行代碼修改?

解決#

外部化所有配置,包括端點URL和憑據。應用程序應該在啓動時或運行時加載它們。Spring Cloud配置服務器提供了將屬性外部化到GitHub並將其作爲環境屬性加載的選項。這些可以在啓動時由應用程序訪問,也可以在不重新啓動服務器的情況下進行刷新。

服務發現#

問題#

當微服務出現時,我們需要在調用服務方面解決一些問題:

1.使用容器技術,IP地址可以動態分配給服務實例。每次地址更改時,消費者服務都會中斷,需要手動更改。
2.每個服務URL都必須由消費者記住並緊密耦合。

那麼,使用者或路由器如何知道所有可用的服務實例和位置?

解決#

需要創建一個服務註冊表,該註冊表將保留每個生產者服務的元數據。服務實例在啓動時應註冊到註冊表,而在關閉時應註銷。消費者或路由器應查詢註冊表,並找出服務的位置。註冊表還需要對生產者服務進行運行狀況檢查,以確保只能通過服務使用服務的工作實例。服務發現有兩種類型:客戶端和服務器端。客戶端發現的一個示例是Netflix Eureka,服務器端發現的一個示例是AWS ALB。

斷路器#

問題#

一個服務通常調用其他服務來檢索數據,並且下游服務可能會關閉。這樣做有兩個問題:首先,請求將繼續進入服務中斷狀態,耗盡網絡資源並降低性能。其次,用戶體驗將是糟糕且不可預測的。我們如何避免級聯服務故障並優雅地處理故障?

解決#

消費者應通過代理來調用遠程服務,該代理的行爲與斷路器相似。當連續的故障數超過閾值時,斷路器會跳閘,並且在超時期間內,所有調用遠程服務的嘗試都會立即失敗。超時到期後,斷路器將允許有限數量的測試請求通過。如果這些請求成功,則斷路器將恢復正常運行。否則,如果發生故障,則超時時間將再次開始。

Netflix Hystrix是斷路器模式的良好實現。它還可以幫助您定義回退機制,該機制可在斷路器跳閘時使用。這樣可以提供更好的用戶體驗。

藍綠部署#

問題#

使用微服務架構,一個應用程序可以具有許多微服務。如果我們停止所有服務,然後部署增強版本,則停機時間將是巨大的,並可能影響業務。同樣,回滾將是一場噩夢。在部署過程中,我們如何避免或減少服務的停機時間?

解決#

可以實施藍綠部署策略以減少或消除停機時間。它通過運行兩個相同的生產環境Blue和Green來實現這一目標。
假設Green是現有的活動實例,而Blue是該應用程序的新版本。在任何時候,只有一個環境處於活動狀態,該活動環境爲所有生產流量提供服務。所有云平臺均提供用於實施藍綠部署的選項。有關此主題的更多詳細信息,請查看本文。


微服務體系結構還有許多其他模式,例如Sidecar,鏈式微服務,分支微服務,事件源模式,連續交付模式等。隨着我們在微服務方面獲得更多經驗,該列表不斷增長。我現在停下來,聽聽您正在使用什麼微服務模式。

關注LZ,後臺私信:“微服務”獲取《微服務實戰學習文檔》及《設計模式精解及面試攻略》

微服務的設計模式

 

 

微服務的設計模式

 

 

微服務的設計模式

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章