共用方式為


微服務架構樣式

微服務是一種熱門的架構樣式,可用來建置具有復原性、高度可調整、可獨立部署且能夠快速發展的應用程式。 建置成功的微服務架構需要思維的基本轉變。 它超越將應用程式分解成較小的服務。 您也必須重新思考系統的設計、部署和運作方式。

微服務架構是由小型自主服務的集合所組成。 每個服務都是獨立的,而且應該在限定的內容內實作單一商務功能。 限定內容是企業內的自然部門,並提供定義域模型存在的明確界限。

微服務架構樣式的邏輯圖表。

什麼是微服務?

微服務是小型、獨立且鬆散結合的元件,可供單一小型開發人員小組撰寫和維護。 每個服務都會以個別的程式代碼基底進行管理,讓小型小組有效率地加以處理。 由於服務可以獨立部署,小組可以更新現有的服務,而不需重建或重新部署整個應用程式。 不同於具有集中式數據層的傳統模型,微服務會負責保存自己的數據或外部狀態。 它們會透過定義完善的 API 進行通訊,讓內部實作與其他服務保持隱藏。 此架構也支援Polyglot程式設計,這表示服務不需要共用相同的技術堆疊、連結庫或架構。

元件

除了服務本身之外,其他元件也會出現在典型的微服務架構中:

  • 管理或協調流程: 此管理元件會處理微服務協調流程。 它會排程及部署跨節點的服務、偵測失敗、從失敗中復原,並根據需求啟用自動調整。 Kubernetes 之類的容器協調流程平臺通常會提供這項功能。 在雲端原生環境中,Azure Container Apps 等解決方案提供協調管理和內建的調整功能。 這些工具可減少部署複雜度和作業額外負荷。

  • API 閘道: API 閘道可作為客戶端的進入點。 用戶端會將要求傳送至 API 閘道,而不是直接呼叫服務。 閘道會將這些要求轉送至適當的後端服務。 它也會處理跨領域考慮,例如驗證、記錄和負載平衡。 在雲端原生微服務架構中,Envoy 和 Nginx 等羽量型服務 Proxy 支援內部服務對服務通訊。 這種類型的內部流量,稱為東西部流量,可啟用進階路由和流量控制。

  • 訊息導向中間件: Apache Kafka 和 Azure 服務總線等傳訊平臺可藉由提升鬆散結合並支援高延展性,在微服務中啟用異步通訊。 它們構成事件驅動架構的基礎。 此方法可讓服務即時回應事件,並透過異步傳訊進行通訊。

  • 可觀察性: 有效的可觀察性策略可協助小組維護系統可靠性並快速解決問題。 集中式記錄會將記錄整合在一起,以支援更輕鬆的診斷。 使用應用程式效能監視代理程式和 OpenTelemetry 等架構進行即時監視,可讓您了解系統健康情況和效能。 分散式追蹤會追蹤跨服務界限的要求。 它可協助小組找出瓶頸並改善效能。

  • 數據管理: 設計良好的資料庫架構支援自主性和延展性。 微服務通常會根據每個服務的特定需求,選擇不同的資料庫類型,例如 SQL 或 NoSQL,以實現多語言持久層。 此方法與領域驅動設計 (DDD) 和限定內容的概念一致。 每個服務都會擁有其數據和架構。 此擁有權可減少跨服務相依性,並允許服務獨立發展。 此分散式模型可改善彈性、效能和系統復原能力。

優點

  • 敏捷: 因為微服務是獨立部署的,所以更容易管理錯誤修正和功能版本。 您可以在不重新部署整個應用程式的情況下更新服務,並在發生問題時回復更新。 在許多傳統應用程式中,如果您在應用程式的某個部分中發現錯誤,它可以封鎖整個發行程式。 例如,如果您需要整合、測試及發佈 Bug 修正,Bug 可能會停止新功能。

  • 小型、專注的團隊: 微服務應該夠小,單一功能小組可以建置、測試及部署微服務。 小型小組大小可提升更大的靈活度。 大型小組的生產力往往較低,因為通訊速度較慢、管理額外負荷增加,而且靈活度會降低。

  • 小型程式代碼基底: 在整合型應用程式中,程式代碼相依性通常會隨著時間而糾纏。 新增功能可能需要變更程式代碼基底的許多部分。 微服務架構可藉由不共用程式代碼或數據存放區來避免此問題。 此方法會將相依性降至最低,並讓您更輕鬆地引進新功能。

  • 混合技術: Teams 可以視需要使用混合技術堆疊來挑選最適合其服務的技術。

  • 錯誤隔離: 如果個別微服務變得無法使用,只要任何上游微服務都設計成正確處理錯誤,它就不會中斷整個應用程式。 例如,您可以實作 斷路器模式,也可以設計解決方案,讓微服務使用 異步傳訊模式彼此通訊。

  • 延展性: 服務可以獨立調整。 此方法可讓您相應放大需要更多資源的子系統,而不需要相應放大整個應用程式。 使用 Kubernetes 之類的協調器,將較高的服務密度新增至單一主機,以達到更有效率的資源使用量。

  • 數據隔離: 更新架構在微服務架構中比較簡單,因為只有一個微服務受到影響。 相反地,整合型應用程式可能會使架構變更複雜,因為多個元件通常會與相同的數據互動。 此共用存取可能會造成任何修改的風險。

挑戰

微服務的優點有取捨。 在建立微服務架構之前,請考慮下列挑戰:

  • 複雜性: 微服務應用程式具有比對等整合型應用程式更多的行動元件。 每個服務會更為簡單,但是系統整個會變得更複雜。 當您設計應用程式時,請務必考慮服務探索、數據一致性、交易管理和服務間通訊等挑戰。

  • 開發和測試: 撰寫依賴其他相依服務的小型服務,需要不同於撰寫傳統整合型或分層式應用程式的方法。 現有的工具不一定是設計來使用服務相依性。 跨服務界限進行重構會很困難。 測試服務相依性也非常困難,尤其是在應用程式快速演進時。

  • 缺乏治理: 建置微服務的分散式方法具有優點,但也可能會導致問題。 您最終可能會有很多不同的語言和架構,而讓應用程式變得難以維護。 備有某些適用於全部專案的標準,而不要過度限制小組的彈性,這樣的做法可能會有幫助。 此方法特別適用於跨領域功能,例如記錄。

  • 網路壅塞和延遲: 使用許多小型、細微的服務可能會導致更多的服務間通訊。 此外,如果服務相依性鏈結變得太長(服務 A 呼叫 B,它會呼叫 C...),額外的延遲可能會變成問題。 您必須仔細設計 API。 請避免過度閒聊的 API、考慮串行化格式,並尋找使用異步通訊模式的地方,例如 Queue-Based 負載撫平模式

  • 數據完整性: 每個微服務都會負責自己的數據持續性。 因此,跨多個服務的數據一致性可能是一項挑戰。 不同的服務會在不同的時間保存數據,使用不同的技術,以及可能不同的成功層級。 當涉及多個微服務在保存新的或已變更的資料時,完全的資料變更不太可能被視為是原子性、一致性、隔離性和持久性(ACID)的交易。 相反地,這項技術更符合「基本可用、柔性狀態、最終一致性」(BASE)。 可能的話,請採用最終一致性。

  • 管理: 成功的微服務架構需要成熟的DevOps文化特性。 在服務之間建立關聯式記錄會非常困難。 一般而言,記錄必須將多個服務呼叫相互關聯到單一使用者作業。

  • 版本控制: 服務的更新不得中斷相依的服務。 多個服務有可能在同一時間一起更新,因此若未謹慎設計,便可能發生回溯相容性或往後相容性問題。

  • 技能集: 微服務是高度分散式的系統。 請謹慎評估小組是否有技能和經驗能夠成功。

最佳做法

  • 建立商務網域周圍的模型服務。 使用 DDD 來識別限定的內容,並定義明確的服務界限。 避免建立過於細微的服務,這可能會增加複雜度並降低效能。

  • 分散所有專案。 個別小組負責設計和建置服務端對端。 避免共用程式代碼或數據架構。

  • 藉由限制您使用的語言和架構數目,將您的技術選擇標準化。 建立全平台的記錄、監視和部署標準。

  • 數據記憶體應該是擁有數據之服務的私用記憶體。 針對每個服務和數據類型使用最佳的記憶體。

  • 服務會透過設計完善的 API 進行通訊。 避免洩漏實作詳細數據。 API 應該建立網域的模型,而不是服務的內部實作。

  • 避免在服務之間結合。 結合的原因包括共用資料庫架構和嚴格的通訊協定。

  • 使用相互傳輸層安全性 (mTLS) 進行服務對服務加密來改善安全性。 實作角色型訪問控制,並使用 API 閘道來強制執行原則。

  • 將身份驗證和安全套接字層終止等橫切關注卸載到閘道。 Dapr 之類的服務網格和架構也可以協助解決常見的跨領域考慮,例如 mTLS 驗證和復原功能。

  • 讓網域知識遠離閘道。 網關應該處理和路由傳送用戶端要求,而不需要瞭解商務規則或網域邏輯。 否則,閘道會變成相依性,而且可能會導致服務之間的結合。

  • 服務應該具有鬆散結合和高功能凝聚力。 可能一起變更的函式應該封裝並部署在一起。 如果它們位於個別的服務中,這些服務最終會緊密結合,因為一個服務中的變更需要更新另一個服務。 兩個服務之間過度閒聊的通訊可能是緊密結合和低凝聚力的癥狀。

  • 使用持續整合和持續部署 (CI/CD) 管線來自動化測試和部署。 獨立部署服務並監視部署狀況。

  • 隔離失敗。 使用復原策略來防止服務內的失敗串連。 如需詳細資訊,請參閱 復原模式設計可靠的應用程式

  • 使用混亂工程來測試微服務架構及其相依性的復原能力。 評估並改善系統如何處理局部故障。

  • 實作集中式記錄、分散式追蹤(OpenTelemetry)和計量集合,以確保可檢視性。

微服務的反模式

當您設計和實作微服務時,通常會發生特定的陷阱,這可能會破壞此架構樣式的優點。 辨識這些反模式可協助小組避免成本高昂的錯誤,並建立更具彈性且可維護的系統。 請避免下列反模式:

  • 實作微服務而無法深入瞭解商務領域會導致服務界限不一致,並破壞預期的優點。

  • 設計依賴過去或未來事件的事件違反了原子性和獨立傳訊的原則。 此相依性會強制取用者等候並降低系統可靠性。

  • 使用資料庫實體作為事件會公開內部服務詳細數據,而且通常無法傳達正確的商務意圖,這會導致緊密結合且不清楚的整合。

  • 避免竭盡所能地避免數據重複是一種反模式。 使用具體化檢視之類的模式來維護本機複本可改善服務自主性,並減少跨服務相依性。

  • 使用泛型事件會強制取用者解譯和篩選訊息。 這種方法會增加不必要的複雜性,並減少事件驅動通訊的明確性。

  • 在微服務之間共用通用連結庫或相依性會建立緊密結合,這會使變更有風險且廣泛,並違反獨立服務的原則。

  • 將微服務直接公開給取用者會導致緊密結合、延展性問題和安全性風險。 使用 API 閘道可提供全新、可管理且安全的進入點。

  • 將組態值保存在微服務內會使它們與特定環境緊密結合,這使得部署變得更困難。 不過,外部化設定可提升彈性和環境可移植性。

  • 將令牌驗證之類的安全性邏輯直接內嵌在微服務中,會使其程式代碼和維護複雜化。 或者,將安全性卸除至專用元件可讓服務保持專注且更簡潔。

  • 無法擷取常見的微服務工作會導致重複且容易出錯的程序代碼,並限制彈性。 或者,使用 Dapr 之類的抽象架構,藉由將商業規則與基礎結構考慮分離來簡化開發。

建置微服務架構

下列文章提供設計、建置及作微服務架構的結構化方法。

使用定義域分析: 若要避免設計微服務時常見的陷阱,請使用定義您的微服務界限領域分析。 執行下列步驟:

  1. 使用領域分析來建立微服務的模型。
  2. 使用戰術 DDD 設計微服務
  3. 識別微服務界限

設計服務: 微服務需要分散且敏捷的方法,才能設計和建置應用程式。 如需詳細資訊,請參閱 設計微服務架構

在生產環境中運作: 由於微服務架構是分散式的,因此您必須有健全的部署和監視作業。