
譯者 | 李騰輝
數十年來,人們一直采用單體構架來開發應用程序,而現在越來越多的人正在轉向微服務架構。微服務架構可以為我們帶來更快的開發迭代速度,更高的可擴展性、可靠性,以及靈活性—使用更合適的技術棧來開發各個組件。微服務架構依賴于各個獨立部署的微服務,每個微服務都有自己獨特的業務邏輯和數據庫,對它的測試、增強和擴縮容也與其他服務無關。然而,微服務架構也面臨著許多挑戰,為了解決那些最常見的問題,一些設計模式被廣泛地采用和改進,本文我們將介紹其中最重要的一部分。
必備的設計模式
在微服務架構中,有超過8種必備的設計模式,根據你正在開發的應用類型不同,我們將它們分為兩大類——綠地應用(Greenfield application)和棕地應用(Brownfield application)。接下來,我們將更詳細地了解這些模式。
適合綠地應用的設計模式
當我們從頭開始設計應用時,我們可以隨心所欲地采用微服務所需的各種最新、最先進的設計模式,現在讓我們來一探究竟。
API網關模式
當你將整個業務拆分為多個微服務時會遇到下述問題:
你如何處理諸如鑒權、限流、重試、負載均衡、服務發現等問題?
你如何避免由于客戶端直連微服務引發的網絡拓撲混亂和耦合過高的問題?
如果客戶端只需要部分數據集,誰來做數據過濾和映射?
如果客戶端需要調用多個微服務才能獲取到完整數據,誰來做數據聚合?
為了解決這些問題,API網關應運而生,它位于客戶端和微服務之間,具有反向代理、請求聚合、優雅下線、服務發現等功能,它還可以根據客戶端的不同選擇暴露不同的API接口。

圖1 – API網關示例UI組合模式
在這種模式下,微服務由負責具體業務的不同團隊開發。而某些UI頁面可能需要來自多個微服務的數據,例如,購物網站包含類目、購物車、購買選項、用戶評價等功能,這些數據歸屬于各個微服務,由不同的團隊負責。如何協調這個問題呢?
UI團隊可以創建一個頁面框架,通過組合多個UI組件來構建完整的頁面,這種框架也稱為單頁應用(SPA, single-page application),像AngularJS 和 ReactJS 等前端框架都支持這一功能。這種模式還帶來了更好的用戶體驗,允許用戶刷新任何指定的頁面區域。
獨立數據庫模式
微服務需要設計得獨立且松耦合,那么對應的數據庫架構應該是怎樣的呢?有以下一些問題需要考量:
一個具體的業務場景可能涉及到多個服務的查詢、聯表、持久化等數據庫操作,而這些服務由不同的團隊負責
在異構的微服務架構中,每個微服務可能有不同的數據存儲要求,如非結構化數據(NoSQL數據庫)、結構化數據(關系型數據庫)、圖數據(Neo4j)
考慮到可伸縮性,數據庫需要有備份和分片

圖2 –服務配置獨立數據庫示例
一個微服務事務必須限制在它自己的數據庫中,其它需要該類數據的服務必須調用這個微服務的API接口。如果你使用的是關系型數據庫,那么每個服務使用自己獨立的庫有利于保證數據的私有性。同時為了更好地隔絕數據訪問,最好為每個服務分配不同的數據庫賬號,這樣確保了開發人員不能繞過微服務的API而直接訪問數據庫。
獨立數據庫模式使得每個微服務都可以選用最合適的數據庫類型,如使用Neo4j用于社交圖數據,使用Elasticsearch用于文本搜索。
Saga模式
當我們為每個服務配置一個獨立數據庫時,在實現跨服務事務時會出現問題,因為在這種情況下,本地ACID已經無法處理,我們如何保證數據一致性呢?解決方式是使用saga模式。saga是指一系列本地事務,其中每個本地事務更新完數據庫后,會發布事件以觸發下一個本地事務,saga模式還要求在任何本地事務失敗時進行補償。
有兩種實現saga模式的方式:
- 編排(Choreography)——去掉控制器,由每個微服務負責監聽和發布事件,并在失敗時啟用補償事件。
控制比編排更容易實現,在控制機制下,只有控制器需要協調所有事件,而在編排中,每個微服務都必須監聽并對事件做出反應。
熔斷模式
在微服務架構中,一個操作會涉及調用多個微服務,如果其中一個下游的服務出現故障,它仍會繼續調用該下游服務,最終導致耗盡所有的網絡資源,同時也會造成較差的用戶體驗。那么我們該如何處理級聯故障呢?
我們從電路斷路器中得到靈感,設計出熔斷模式來解決這個問題。具體來說,在客戶端和微服務之間,會設置一個熔斷器,用于追蹤失敗調用的次數,如果它超過閾值,它將觸發熔斷并快速失敗。在一段時間之后,熔斷器會再允許小部分請求通過來檢測服務是否正常,如正常則恢復流量,否則繼續保持斷路一段時間。

圖3 –熔斷器狀態機
按業務或子域劃分模式
在微服務架構中,復雜的大型應用必須做到合理劃分、高內聚、低耦合,每個微服務還應該是自治的,并且足夠小,可以由"批薩大小"的團隊(6-8人)開發維護。那么,我們應該怎么劃分服務呢?
總體來說有兩種劃分方式——按業務能力或者子域:
業務能力是指可以產生價值的行為,例如,在一家航空公司中,業務能力可以是預訂、銷售、支付、座位分配等;子域概念來自于領域驅動設計(Domain-Design Pattern, DDD),一個領域由多個子域組成,如產品目錄、訂單管理、配送管理等。
適合棕地應用的設計模式
由于互聯網應用已經發展了數十年,大約有80%的公司的業務是基于現有的應用運作的,這些應用被稱作棕地應用。將棕地應用程序遷移到微服務架構是極具挑戰性的工作。讓我們看看有哪些設計模式可以幫助我們更好地簡化遷移的工作。
扼殺者模式
扼殺者模式,取名來自于藤蔓這種植物,它通過纏繞殺死它所依附的樹木。在這種模式下,單體應用的各功能被逐步地被替換為微服務,而對于客戶端來說,由于外部API保持不變,客戶端感知不到任何變化,隨著轉換進度的推進,最終所有功能都被重構為微服務,新架構"扼殺"取代了原來的單體架構。
防腐層模式
當新應用需要與遺留應用集成時,過時的基礎協議、API和數據模型是一個讓人頭大的難題。如果妥協沿用舊模式和舊語義,可能會限制和破壞新應用的技術設計。要如何才能避免這個問題呢?
我們需要新增一個防腐層來轉換兩個系統之間的通信,防腐層同時兼容新應用和舊應用的數據模型,并根據與它通信的對象決定采用哪種通信方式。這樣就實現了雙贏,既不用更改舊應用邏輯,也確保新應用無需在設計和技術上做妥協。

圖4 –防腐層示例
總結
微服務架構為開發人員帶來了很大的靈活性,但隨著要管理的組件數量的增加,也帶來了許多難題。在本文中,我們介紹了對于微服務應用開發來說最必不可少的幾種設計模式,供讀者了解和學習。
譯者介紹
李騰輝,51CTO社區編輯,目前在一家東南亞互聯網金融獨角獸擔任資深Java工程師,負責金融借貸平臺架構設計及核心建設工作,對互聯網金融架構、微服務體系有較深入的研究,期望在互金領域持續深耕。
原文標題:Popular Design Patterns for Microservices Architectures,作者:Rajesh Bhojwani
鏈接:https://dzone.com/articles/popular-design-patterns-for-microservices-architec

































