微服務設計模式
3.1 服務拆分
根據領域模型進行拆分
根據領域模型進行拆分,不大於一個邊界上下文,不小於一個聚合。
3.2 程序通訊
通訊方式 |
概要 |
|
同步通訊 |
REST |
使用http動詞來操作資源, 客戶端和伺服器端通過http/json進行通訊。弊端是動詞有限 |
dubbo |
分為介面和實現兩部分,介面需單獨打包,在服務提供方和消費方共享;實現部分對外暴露介面,客戶端通過該介面進行RPC呼叫。 |
|
非同步通訊 |
非同步訊息 |
訊息通道型別:點對點、釋出/訂閱。 併發:通道分片。 訊息重複:訊息流水錶排重,對messageid做唯一性約束。 事務性訊息:2PC |
3.3 服務間查詢
查詢模式 |
適用場景 |
Api介面組合模式 |
不需要進行大量資料連線 |
CQRS模式 |
需要進行大量資料連線 |
3.4 api閘道器
3.4.1 介面組織形式
後端前置模式
為每一種型別的客戶端實現單獨的api閘道器。
1.5 分散式事務
1.5.1 分散式事務協議
2PC。
1.5.2 分散式事務實現模式
所有模式均基於2PC實現。
實現方式 |
原理 |
存在的問題 |
適用場景 |
XA模式 |
嚴格遵循2PC協議,由支援XA協議的資料庫進行事務控制 |
併發效能低下 |
適合強一致性場景 |
SAGA模式 |
將一個長事務分成一組子事務,每個子事務定義一個逆向的補償事務。子事務同樣採用2PC,一階段順序呼叫子事務,如果都執行成功則二階段什麼也不做;如果發生異常,則自動呼叫補償事務回滾。 |
不保證隔離性 |
適合長事務,並保證最終一致性的業務系統 |
TCC模式 |
增加資源預留狀態,一階段鎖定資源,如果資源鎖定都成功,二階段對鎖定資源執行業務邏輯,否則對鎖定資源進行釋放。 |
保證隔離性 |
高效能分散式事務解決方案,適用於核心系統等對效能有要求的場景。 |
可靠訊息最終一致模式 |
一階段服務正常呼叫,二階段進行訊息投遞,消費。 |
最終一致性 |
使用事務協調器,定義了兩種型別的鎖:全域性鎖和本地鎖。獲得本地鎖才能執行事務,獲得全域性鎖才能提交事務。通過兩種鎖實現事務之間的隔離。
對於本地事務,通過對SQL進行代理,生成undo log。回滾時,本地事務執行undo log。
1.6 斷路器
當一個服務同步呼叫另一個服務時,應使用如下方式:
1) 呼叫方設定超時時間;
2) 被呼叫方限制請求數量;
3) 被呼叫方設定斷路器
3.6.1限流演算法
演算法 |
原理 |
適用場景 |
實現 |
令牌桶 |
勻速生成令牌,請求獲得令牌才能執行 |
讀寫分離時,限制寫的速度 |
使用ratelimiter+佇列實現 |
漏桶 |
生產者向桶裡寫入資料,消費者按照固定速度去消費資料 |
讀寫分離時,限制讀的速度 |
使用ratelimiter+佇列實現 |
令牌桶和流通都是按照QPS的維度去限流,限制併發數可以使用訊號量實現。
在zuul閘道器上配置ratelimiter限流:
zuul:
ratelimit:
enabled: true
repository: REDIS #對應儲存型別(用來儲存統計資訊)
behind-proxy: true #代理之後
default-policy: #可選 - 針對所有的路由配置的策略,除非特別配置了policies
limit: 10 #可選- 每個重新整理時間視窗對應的請求數量限制
refresh-interval: 60 # 重新整理時間視窗的時間,預設值 (秒)
type: #可選 限流方式
- url
policies:
myServiceId: #針對特定路由進行限流
limit: 10 #可選- 每個重新整理時間視窗對應的請求數量限制
refresh-interval: 60 # 重新整理時間視窗的時間,預設值 (秒)
type: #可選 限流粒度
- url
3.6.2隔離和異常
服務保護和介面隔離
一個服務通常有多個介面,為了防止因為某個介面呼叫異常導致服務整體崩潰,對特定介面的請求進行隔離,介面之間互不影響。
策略 |
適用場景 |
優缺點 |
執行緒池 |
高併發 |
優點是支援瞬時的高流量,缺點是執行緒切換開銷大。 |
訊號量 |
併發量不高 |
優點是執行緒切換開銷小,缺點是不支援瞬時高流量。 |
異常處理:降級熔斷
熔斷器控制異常的處理,執行降級邏輯或拒絕請求。
在閘道器上配置hystrix熔斷器:
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 3000
基於zuul上的功能增強均是過濾器。
3.7 鏈路追蹤(skywalking)
基於java agent實現。
1) 拷貝agent目錄到所需位置,日誌、外掛和配置都包含在包中,請不要改變目錄結構;
2) 增加JVM啟動引數, -javaagent:/path/to/skywalking-agent/skywalking-agent.jar. 引數值為skywalking-agent.jar的絕對路徑。
3.8 服務發現
需要服務發現的原因:服務例項和IP地址是動態的,而不是靜態的,所以需要服務發現。
服務發現的核心是服務登錄檔。
服務發現方式 |
註冊方式 |
發現模式 |
優點 |
缺點 |
應用層服務發現 |
服務例項自注冊 |
客戶端發現 |
可以處理多平臺部署問題 |
需要為使用的語言提供服務發現庫 |
平臺層服務發現 |
註冊器自動註冊 |
平臺路由器發現 |
客戶端和服務端都不包含服務發現程式碼,不需要為不同語言提供服務發現庫 |
僅支援在該平臺上部署的服務 |
3.9 外部配置(Apollo)
3.10 許可權管理
3.10.1 服務層鑑權
使用基於角色的許可權控制(USER-ROLE-PERMISSION),實現框架有Spring Security或Shiro。
3.10.2 閘道器層鑑權
使用OAuth2 + token的方式。Oauth2主要使用密碼模式和授權碼模式。
密碼模式:
1) 使用者使用使用者名稱和密碼從認證伺服器獲取token
2) 使用者使用token訪問資源伺服器
3) 資源伺服器使用token獲取使用者資訊
4) 資源伺服器鑑權
授權碼模式:
1) 使用者使用使用者名稱密碼從認證伺服器換取授權碼
2) 使用者使用授權碼訪問oauth客戶端
3) 客戶端使用授權碼到授權伺服器換取訪問令牌
4) 客戶端使用訪問令牌訪問資源伺服器