[TOC]
Microservices.io官網給我們提供了一套微服務的方法論,就是有關微服務架構會用到的“模式語言”。
A pattern language is a method of describing good design practices or patterns of useful organization within a field of expertise.
一、核心
問題:應用的架構是什麼?
1單體模式
整個應用打包成一個war包,部署在web容器內,系統按照MVC模式分成表示層、模型層、控制層三層。
優點:易於開發、測試、部署,水平擴展。
缺點:隨着系統功能越來越多,越來越不便於理解和變更,可擴展性低,難以滿足持續集成部署,無法及時響應敏捷開發。
2微服務模式
整個架構由一系列鬆散耦合的服務組成。每個服務提供一組內部關聯的功能,如訂單管理、客戶管理。服務之間通過HTTP同步通信,通過AMQP異步通信。每個服務可以有自己的數據庫,可獨立開發、部署。
二、分解
問題:如何把單體分解成多個服務?
1按業務能力
業務能力是業務架構建模的概念。這是企業爲了創造價值而做的事情。業務能力通常對應於業務對象,例如櫃員管理、機構管理、產品管理、權限管理、參數管理、流水管理、流程管理、貸款管理、客戶管理、賬號管理、額度管理等。
2按子領域
將服務定義爲與領域域驅動設計(DDD)子域對應。DDD指的是應用程序將業務作爲領域。一個域由多個子域組成。每個子域對應於業務的不同部分。
分解的核心就是按照業務部門的組織架構找出相應的領域對象。
三、部署
問題:如何部署微服務?
單機多實例
單機單實例
單虛擬機單實例
單容器單實例
Serverless平臺
PaaS平臺
四、橫切關注點
問題:如何讓微服務不需修改就能在多種環境運行(開發、測試、生產)?
外部化配置
通過將服務的配置外部化,讓微服務在啓動的時候從外部環境獲取到所有配置信息。
五、通信方式
問題:如何實現微服務之間的通信?
1.RPI遠程過程調用
通過基於請求/響應的協議實現服務間、客戶端與服務間的通信,如REST、Apache Thrift、gRPC。
優點:
請求/響應的方式簡單直接;
沒有中間代理,簡化了通信過程;
缺點:
不支持請求/異步響應,發佈/訂閱,發佈/異步響應等通信模式;
客戶端和服務之間的延時可能會降低可用性;
2.消息通信
通過異步消息實現服務間的通信,如Apache Kafka、RabbitMQ。
優點:
服務之間可以鬆耦合;
由消息代理緩存消息提高服務可用性;
支持多種通信模式:請求/響應,通知,請求/異步響應,發佈/訂閱,發佈/異步響應。
缺點:
消息代理讓通信方式更加複雜,需要保證高可用;
3.特定協議
使用特定協議實現服務間通信,如郵件協議SMTP,IMAP,流媒體協議RTMP,HLS,HDS。
六、外部API
問題:如何對外發布微服務的api給其他客戶端調用?
1.API網關
通過對外提供一個統一的API網關入口,負責轉發客戶端的請求到對應的服務。將前後端分離,避免客戶端對微服務直接請求。
也可以是針對不同的客戶端提供不同的api網關入口
七、服務發現
問題:如何讓客戶端找到可用的微服務?
服務註冊
由一個服務註冊中心來維護可用服務的清單,微服務啓動的時候將自己的實例信息、位置發送到註冊中心進行登記,關閉的時候向註冊中心註銷。註冊中心如:Apache Zookeeper,Eureka,Consul。
客戶端的服務發現
服務端的服務發現
八、可用性
問題:如何防止網絡或服務失敗從級聯到其他服務?
斷路器
客戶端通過代理方式調用遠程服務,從而使其類似電路斷路器。當連續故障數超過閾值或超時,斷路器被觸發,所有調用遠程服務的嘗試直接失敗。超時結束後,斷路器允許重試,如果請求成功,斷路器恢復正常運行。否則,如果出現故障,重新計算超時時間。
九、數據管理
單服務單數據庫
共享數據庫
問題:如何維護跨服務之間的數據一致性?
當每個微服務一個數據庫時,對於跨服務的交易需要有保證數據一致性的機制,因爲不能直接使用本地的ACID事務控制。
1.Saga
將跨多個服務的業務事務使用Saga實現。Saga是本地事務的一個隊列。每個本地事務都更新數據庫併發布消息或事件來觸發該事件中的下一個本地事務。如果本地事務失敗,或違反了業務規則,則該事件執行一系列補償事務,撤消前面本地事務所做的更改。
優點:
它允許應用程序在不使用分佈式事務的情況下維護跨服務的數據一致性。 缺點:
程序更加複雜。例如,需要設計補償事務,用於撤消了先前所做的更改。 服務必須自動更新其數據庫併發布事件。因爲不能使用傳統的分佈式事務的機制。Saga依賴下面列出的模式。
問題:如何在狀態更改時原子性的發佈事件?
2.事件溯源
事件溯源通過一個狀態變化事件的隊列來保存業務實體的狀態。每當業務實體的狀態發生變化時,就添加一個新事件到事件隊列中,這個動作是原子性的。可以通過重放這些事件來重構業務實體的當前狀態。事件保存在一個事件倉庫中,提供api用於添加事件和查詢業務實體的事件。
優點:
它解決了事件驅動架構中的一個關鍵問題,即在狀態更改時可靠地發佈事件;
它提供了100%份可靠的審計日誌,記錄了對業務實體所做的更改;
它使得能夠實現時間查詢來確定某個實體在任何時刻的狀態;
基於事件驅動的業務實體是鬆耦合的,這使得更容易從單體應用程序遷移到基於微服務的架構。
缺點:
這是一種不同的編程風格,會有學習曲線;
事件存儲很難查詢,需要特定的查詢方式來重構業務實體的狀態,增加了複雜度;
應用程序必須使用命令查詢責任隔離(CQRS)來實現查詢;
應用程序須處理數據的最終一致性。
3.交易日誌追蹤
追蹤數據庫事務日誌並將每個更改發佈爲事件。
優點:
不用2pc;
不需要更改應用程序;
保證準確;
缺點:
很複雜;
針對特定數據庫的解決方案;
很難避免重複發佈;
低級別db更改難以確定業務級別事件。
4.數據庫觸發器
通過一個或多個數據庫觸發將事件插入事件表,由單獨的進程輪詢該事件表發佈事件。
優點:
高級別域事件;
不用2pc
缺點:
需要對應用程序進行更改,易出錯;
很難避免重複發佈;
很難按順序發佈事件;
只適用於sql型數據庫;
5.應用事件
通過應用程序將事件插入事件表作爲本地事務的一部分。由單獨的進程輪詢事件表並將事件發佈到消息代理中。
問題:如何在多微服務間實現查詢?
6.API組合器
通過定義一個api組合器來實現查詢,該api調用擁有數據的服務並在內存實現結果join連接。
7.CQRS
將應用程序拆分爲兩個部分:命令端和查詢端。命令端負責創建、更新和刪除,並在數據發生更改時發出事件。查詢端通過執行一個或多個物化視圖來處理查詢,通過訂閱數據更改時發出的事件流來保持最新的物化視圖。
十、安全
問題:如何將請求者的身份傳遞給處理請求的服務?
訪問Token
由api網關驗證請求並傳遞訪問令牌,該令牌標識請求者向服務發送請求。服務可以在請求加入令牌進行對其他服務的請求。
十一、測試
問題:如何測試服務是否提供了客戶端想要的api?
合約測試Contract Test
由服務的調用者來提供一個合約,表明該服務應該提供的功能。測試驗證服務符合服務消費者的期望。
十二、可監控性
問題:如何觀察應用程序的行爲並排除問題?
日誌集合
收集各個服務的應用日誌,用於分析。
應用指標
收集關於個別操作的統計信息和各種指標。有兩個用於聚合度量的模型:
推送-服務將度量推到度量服務;
拉取-度量服務從服務中提取度量;
審計日誌
把用戶活動記錄在數據庫中。
分佈式鏈路追蹤
通過請求id記錄請求的交易的鏈路。
健康檢查
服務提供一個健康檢查api端點,用於外部查詢該服務的可用狀態。