微服務架構中 10 個常用的設計模式

軟件設計模式是解決軟件設計中常見問題的通用、可複用的解決方案。設計模式讓我們可以分享通用詞彙並使用經實戰檢驗的方案,以免重複造輪子。我先簡單介紹下微服務架構。

通過閱讀這篇文章,你會學到:

最重要的微服務架構設計模式,包括其優缺點、用例、上下文、技術棧示例及可用資源。

請注意,本清單中的大部分設計模式常出現在多種語境中,並且可以在非微服務架構中使用。而我將在微服務這個特定語境中介紹它們。

1 微服務架構

我在之前的博客《微服務架構概述及爲什麼要應用在下個項目》和《單體軟件架構真的終結了嗎?》中對微服務架構有非常詳盡的介紹。如果你感興趣,可以閱讀這兩篇博客來深入瞭解。

https://towardsdatascience.com/microservice-architecture-a-brief-overview-and-why-you-should-use-it-in-your-next-project-a17b6e19adfd

https://towardsdatascience.com/looking-beyond-the-hype-is-modular-monolithic-software-architecture-really-dead-e386191610f8

那到底什麼是微服務架構?有很多種定義方法。我的定義是這這樣的:

微服務架構指的是將大型複雜系統按功能或者業務需求垂直切分成更小的子系統,這些子系統以獨立部署的子進程存在,它們之間通過輕量級的、跨語言的同步(比如 REST,gRPC)或者異步(消息)網絡調用進行通信。

下面是基於微服務架構的商業 Web 應用的組件視圖:

來自 Md Kamaruzzaman 的微服務架構

 微服務架構的重要特徵

 微服務架構的優點

 微服務架構的缺點

 何時使用微服務架構

2 微服務架構的設計模式

 獨享數據庫(Database per Microservice)

當一家公司將大型單體系統替換成一組微服務,首先要面臨的最重要決策是關於數據庫。單體架構會使用大型中央數據庫。即使轉移到微服務架構許多架構師仍傾向於保持數據庫不變。雖然有一些短期收益,但它卻是反模式的,特別是在大規模系統中,微服務將在數據庫層嚴重耦合,整個遷移到微服務的目標都將面臨失敗(例如,團隊授權、獨立開發等問題)。

更好的方法是爲每個微服務提供自己的數據存儲,這樣服務之間在數據庫層就不存在強耦合。這裏我使用數據庫這一術語來表示邏輯上的數據隔離,也就是說微服務可以共享物理數據庫,但應該使用分開的數據結構、集合或者表,這還將有助於確保微服務是按照領域驅動設計的方法正確拆分的。

Md Kamaruzzaman 的微服務獨享數據庫

優點

缺點

何時使用獨享數據庫

何時不宜使用獨享數據庫

可用技術示例

所有 SQL、 NoSQL 數據庫都提供數據的邏輯分離(例如,單獨的表、集合、結構、數據庫)。

 事件源(Event Sourcing)

在微服務架構中,特別使用獨享數據庫時,微服務之間需要進行數據交換。對於彈性高可伸縮的和可容錯的系統,它們應該通過交換事件進行異步通信。在這種情況,您可能希望進行類似更新數據庫併發送消息這樣的原子操作,如果在大數據量的分佈式場景使用關係數據庫,您將無法使用兩階段鎖協議(2PL),因爲它無法伸縮。而 NoSQL 數據庫因爲大多不支持兩階段鎖協議甚至無法實現分佈式事務。

在這些場景,可以基於事件的架構使用事件源模式。在傳統數據庫中,直接存儲的是業務實體的當前 “狀態”,而在事件源中任何“狀態” 更新事件或其他重要事件都會被存儲起來,而不是直接存儲實體本身。這意味着業務實體的所有更改將被保存爲一系列不可變的事件。因爲數據是作爲一系列事件存儲的,而非直接更新存儲,所以各項服務可以通過重放事件存儲中的事件來計算出所需的數據狀態。

Md Kamaruzzaman 的事件源

優點

缺點

何時使用事件源

何時不宜使用事件源

可用技術示例

事件存儲:EventStoreDB、Apache Kafka、Confluent Cloud、AWS Kinesis、Azure Event Hub、GCP Pub/Sub、Azure Cosmos DB、MongoDB、Cassandra、Amazon DynamoDB

框架:Lagom、Akka、Spring、akkatecture、Axon、Eventuate

 命令和查詢職責分離(CQRS)

如果我們使用事件源,那麼從事件存儲中讀取數據就變得困難了。要從數據存儲中獲取實體,我們需要處理所有的實體事件。有時我們對讀寫操作還會有不同的一致性和吞吐量要求。

這種情況,我們可以使用 CQRS 模式。在該模式中,系統的數據修改部分(命令)與數據讀取部分(查詢)是分離的。而 CQRS 模式有兩種容易令人混淆的模式,分別是簡單的和高級的。

在其簡單形式中,不同實體或 ORM 模型被用於讀寫操作,如下所示:

Md Kamaruzzaman 的 CQRS (簡單)

在其高級形式中,會有不同的數據存儲用於讀寫操作。高級的 CQRS 通常結合事件源模式。根據不同情況,會使用不同類型的寫數據存儲和讀數據存儲。寫數據存儲是 “記錄的系統”,也就是整個系統的核心源頭。

Md Kamaruzzaman 的 CQRS(高級)

對於讀頻繁的應用程序或微服務架構,OLTP 數據庫(任何提供 ACID 事務保證的關係或非關係數據庫)或分佈式消息系統都可以被用作寫存儲。對於寫頻繁的應用程序(寫操作高可伸縮性和大吞吐量),需要使用寫可水平伸縮的數據庫(如全球託管的公共雲數據庫)。標準化的數據則保存在寫數據存儲中。

對搜索(例如 Apache Solr、Elasticsearch)或讀操作(KV 數據庫、文檔數據庫)進行優化的非關係數據庫常被用作讀存儲。許多情況會在需要 SQL 查詢的地方使用讀可伸縮的關係數據庫。非標準化和特殊優化過的數據則保存在讀存儲中。

數據是從寫存儲異步複製到讀存儲中的,所以讀存儲和寫存儲之間會有延遲,但最終是一致的。

優點

缺點

何時使用 CQRS

何時不宜使用 CQRS

可用技術示例

寫存儲:EventStoreDB, Apache Kafka, Confluent Cloud, AWS Kinesis, Azure Event Hub, GCP Pub/Sub, Azure Cosmos DB, MongoDB, Cassandra. Amazon DynamoDB

讀存儲:Elastic Search, Solr, Cloud Spanner, Amazon Aurora, Azure Cosmos DB, Neo4j

框架:Lagom, Akka, Spring, akkatecture, Axon, Eventuate

 Saga

如果微服務使用獨享數據庫,那麼通過分佈式事務管理一致性是一個巨大的挑戰。你無法使用傳統的兩階段提交協議,因爲它要麼不可伸縮(關係數據庫),要麼不被支持(多數非關係數據庫)。

Md Kamaruzzaman 的 Saga

如果本地事務失敗,Saga 將執行一系列補償事務來回滾前面本地事務的更改。

Saga 事務協調管理主要有兩種形式:

  1. 事件編排 Choreography:分散協調,每個微服務生產並監聽其他微服務的事件或消息然後決定是否執行某個動作。

  2. 命令編排 Orchestration:集中協調,由一個協調器告訴參與的微服務哪個本地事務需要執行。

優點

缺點

何時使用 Saga

何時不宜使用 Saga

可用技術示例

Axon, Eventuate, Narayana

 面向前端的後端 (BFF)

在現代商業應用開發,特別是微服務架構中,前後端應用是分離和獨立的服務,它們通過 API 或 GraphQL 連接。如果應用程序還有移動 App 客戶端,那麼 Web 端和移動客戶端使用相同的後端微服務就會出現問題。因爲移動客戶端和 Web 客戶端有不同的屏幕尺寸、顯示屏、性能、能耗和網絡帶寬,它們的 API 需求不同。

面向前端的後端模式適用於需要爲特殊 UI 定製單獨後端的場景。它還提供了其他優勢,比如作爲下游微服務的封裝,從而減少 UI 和下游微服務之間的頻繁通信。此外,在高安全要求的場景中,BFF 爲部署在 DMZ 網絡中的下游微服務提供了更高的安全性。

Md Kamaruzzaman 的面向前端的後端

優點

缺點

何時使用 BFF

何時不宜使用 BFF

可用技術示例

任何後端框架(Node.js,Spring,Django,Laravel,Flask,Play,…)都能支持。

 API 網關

在微服務架構中,UI 通常連接多個微服務。如果微服務是細粒度的(FaaS) ,那麼客戶端可能需要連接非常多的微服務,這將變得繁雜和具有挑戰性。此外,這些服務包括它們的 API 還將不斷進化。大型企業還希望能有其他橫切關注點(SSL 終止、身份驗證、授權、節流、日誌記錄等)。

一個解決這些問題的可行方法是使用 API 網關。API 網關位於客戶端 APP 和後端微服務之間充當 facade,它可以是反向代理,將客戶端請求路由到適當的後端微服務。它還支持將客戶端請求扇出到多個微服務,然後將響應聚合後返回給客戶端。它還支持必要的橫切關注點。

Md Kamaruzzaman 的 API 網關

優點

缺點

何時使用 API 網關

何時不宜使用 API 網關

可用技術示例

Amazon API 網關, Azure API 管理, Apigee, Kong, WSO2 API 管理器

 Strangler

如果想在運行中的項目中使用微服務架構,我們需要將遺留的或現有的單體應用遷移到微服務。將現有的大型在線單體應用程序遷移到微服務是相當有挑戰性的,因爲這可能破壞應用程序的可用性。

一個解決方案是使用 Strangler 模式。Strangler 模式意味着通過使用新的微服務逐步替換特定功能,將單體應用程序增量地遷移到微服務架構。此外,新功能只在微服務中添加,而不再添加到遺留的單體應用中。然後配置一個 Facade (API 網關)來路由遺留單體應用和微服務間的請求。當某個功能從單體應用遷移到微服務,Facade 就會攔截客戶端請求並路由到新的微服務。一旦遷移了所有的功能,遺留單體應用程序就會被 “扼殺(Strangler)”,即退役。

Md Kamaruzzaman 的 Strangler

優點

缺點

何時使用 Strangler

何時不宜使用 Strangler

可用技術示例

API 網關後端應用框架。

 斷路器

在微服務架構中,微服務通過同步調用其他服務來滿足業務需求。服務調用會由於瞬時故障(網絡連接緩慢、超時或暫時不可用) 導致失敗,這種情況重試可以解決問題。然而,如果出現了嚴重問題(微服務完全失敗),那麼微服務將長時間不可用,這時重試沒有意義且浪費寶貴的資源(線程被阻塞,CPU 週期被浪費)。此外,一個服務的故障還會引發整個應用系統的級聯故障。這時快速失敗是一種更好的方法。

在這種情況,可以使用斷路器模式挽救。一個微服務通過代理請求另一個微服務,其工作原理類似於電氣斷路器,代理通過統計最近發生的故障數量,並使用它來決定是繼續請求還是簡單的直接返回異常。

Md Kamaruzzaman 的斷路器

斷路器可以有以下三種狀態:

  1. 關閉:斷路器將請求路由到微服務,並統計給定時段內的故障數量,如果超過閾值,它就會觸發並進入打開狀態。

  2. 打開:來自微服務的請求會快速失敗並返回異常。在超時後,斷路器進入半開啓狀態。

  3. 半開:只有有限數量的微服務請求被允許通過並進行調用。如果這些請求成功,斷路器將進入閉合狀態。如果任何請求失敗,斷路器則會進入開啓狀態。

優點

缺點

何時使用斷路器

何時不宜使用斷路器

可用技術示例

API 網關,服務網格,各種斷路器庫(Hystrix, Reselience4J, Polly)。

 外部化配置

每個業務應用都有許多用於各種基礎設施的配置參數(例如,數據庫、網絡、連接的服務地址、憑據、證書路徑)。此外在企業應用程序通常部署在各種運行環境(Local、 Dev、 Prod)中,實現這些的一個方法是通過內部配置。這是一個致命糟糕實踐,它會導致嚴重的安全風險,因爲生產憑證很容易遭到破壞。此外,配置參數的任何更改都需要重新構建應用程序,這在在微服務架構中會更加嚴峻,因爲我們可能擁有數百個服務。

更好的方法是將所有配置外部化,使得構建過程與運行環境分離,生產的配置文件只在運行時或通過環境變量使用,從而最小化了安全風險。

優點

 消費端驅動的契約測試

優點

缺點

何時使用需求驅動的契約測試

何時不宜使用消費端驅動的契約測試

可用技術示例

Pact, Postman, Spring Cloud Contract

3 總結

在現代大規模企業軟件開發中,微服務架構能夠幫助開發擴展規模並帶來很多長期收益。但是微服務架構並不是隨處可用的銀彈,如果應用在錯誤的應用程序類型,微服務架構將弊大於利。希望採用微服務架構的開發團隊應該遵循最佳實踐,並使用一系列可重用的、久經錘鍊的設計模式。

微服務架構中至關重要的設計模式是獨享數據庫。實現這種設計模式具有挑戰性,需要其他幾種密切相關的設計模式(事件驅動、 CQRS、 Saga)來支持。在具有多個客戶端(Web、 Mobile、 Desktop、 Smart Devices)的典型業務應用程序中,客戶端和微服務之間的通信量可能是很大的,並且需要統一的安全控制,在這種情況面向前端的後端和 API 網關的設計非常有用。此外,斷路器模式可以大大地幫助應對這類應用程序的錯誤處理場景。遷移遺留的單體應用到微服務是極具挑戰性的,而 Strangler 模式可以幫助做到這點。消費端驅動的契約測試是微服務集成測試的基礎模式。另外外部化配置是任何現代化應用程序開發中的一種必備模式。

這個系列並不全面,在實際情況中您可能需要其他的設計模式,但這個系列能爲您提供一個關於微服務架構設計模式的極好介紹。

原文鏈接:

https://towardsdatascience.com/microservice-architecture-and-its-10-most-important-design-patterns-824952d7fa41

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/kcb_L1cI6FQnR3vMc8toFg