微服務是一種熱門的架構樣式,可用來建置具有復原性、高度可調整、可獨立部署且能夠快速發展的應用程式。 建置成功的微服務架構需要思維的基本轉變。 它超越將應用程式分解成較小的服務。 您也必須重新思考系統的設計、部署和運作方式。
微服務架構是由小型自主服務的集合所組成。 每個服務都是獨立的,而且應該在限定的內容內實作單一商務功能。 限定內容是企業內的自然部門,並提供定義域模型存在的明確界限。
什麼是微服務?
微服務是小型、獨立且鬆散結合的元件,可供單一小型開發人員小組撰寫和維護。 每個服務都會以個別的程式代碼基底進行管理,讓小型小組有效率地加以處理。 由於服務可以獨立部署,小組可以更新現有的服務,而不需重建或重新部署整個應用程式。 不同於具有集中式數據層的傳統模型,微服務會負責保存自己的數據或外部狀態。 它們會透過定義完善的 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 之類的抽象架構,藉由將商業規則與基礎結構考慮分離來簡化開發。
建置微服務架構
下列文章提供設計、建置及作微服務架構的結構化方法。
使用定義域分析: 若要避免設計微服務時常見的陷阱,請使用定義您的微服務界限領域分析。 執行下列步驟:
設計服務: 微服務需要分散且敏捷的方法,才能設計和建置應用程式。 如需詳細資訊,請參閱 設計微服務架構。
在生產環境中運作: 由於微服務架構是分散式的,因此您必須有健全的部署和監視作業。
相關資源
- 在 Kubernetes 上建置微服務的 CI/CD 管線
- 微服務架構的 CI/CD
- Azure Kubernetes Service (AKS) 的微服務架構