作者:潘罡 (Van Pan) @ Microsoft
上節中我們談到了Service Fabric最底層的兩個概念,一個是針對硬件層面而言的Node Type和Node。另一個是Application。
Node Type是Node的集合,Node是對部署機器的概念抽象。對Service Fabric而言,Node可以是物理機,虛擬機,甚至現在最主流的Container。
在Node Type上運行的是Application。它是針對系統軟件層面的抽象理解。一個Application中包含了多個Micro Service。甚至Service Fabric的所有基礎服務,例如FailoverManager Service,Naming Service,也都是Micro Service。
Service Fabric所有分布式特性都對應於Micro Service展開。我們可以動態調整一個Micro Service需要在多少個Node上運行多少個實例來分攤負載壓力,或者進行容災備份。每一個實例都會監聽不同的端口,由負載均衡層將請求分布至不同實例上。
實際場景
Stateful Service是其中的一種Micro Service。
在開始介紹Stateful Service之前,讓我們來考慮下面這種很常見的業務場景。
你正在考慮實現網站里面的購物車功能。用戶登錄后會放置一些商品在自己的購物車中。
用戶下次登錄,前台頁面會調用購物車服務,並需要從這個服務重新讀取已經保存的購物車數據並用以顯示。
如果是你會怎么實現?
如果在用戶量不是特別大的一般情況下,我們會在數據庫中添加一張購物車表,和用戶表進行關聯。該購物車表中會有一個用戶ID字段,並且記錄大量的用戶購物車數據。
那么這樣就會帶來一些后續問題。
- 如果用戶量持續增加,數據庫表的性能會持續下降。
- 數據庫表數據需要定期備份,以防數據丟失
- 如果數據庫性能出現問題,需要將表進行拆表處理,甚至需要將表進行分區
- 購物車系統自身也需要針對數據庫的任何調整進行處理,甚至它自身可能也需要做負載均衡
這種問題的根源在於,首先系統本身的設計不是面向可擴展的。另外數據庫是一個性能潛在的瓶頸和威脅。
Stateful Service
讓我們考慮這樣一種全新的架構。
從一開始,購物車系統就由36個子服務來處理所有的請求(36個是因為用戶ID的首字母是 0-9 a-z,一共36種)。
用戶的請求,會根據用戶ID首字母hash至某個特定的子服務來處理。
子服務把購物車數據通過輕量級數據庫方式保存在自己內部,並且持久化到自己所在的存儲設備上。
每個子服務還有3個備份,這些備份在不停同步保存的數據,同時這些備份永遠運行在不同的Node上。
同時只有一個備份作為激活狀態來負責處理請求,當激活備份出現問題,另外兩個備份根據調度算法激活一個。
容災子系統再創建一個新的備份,永遠保證該子服務有3個健康的備份。
Stateful Service就是這樣的一種解決方案。
回到上面的場景,購物車系統就是一個Stateful Service。
36個子系統就是這個Stateful Service的36個實例,我們叫Partition。
每個子系統下的備份就是Replica,一個partition有3個Replica。
當前激活的備份就是Active Replica,兩個未激活的待命備份就是Secondary Replica。
同一個Partiion的每個Replica都一定運行在不同的Node上面。
Stateful Service代碼通過IReliableCollection<T>,IReliableDictionary<T1, T2>等接口來進行數據保存和內部同步。
此外,Stateful Service還可以實現以下特性。
- 以上所有的數字都可以重新設置,你可以讓購物車系統有幾百個partition來負載更大的壓力。你甚至可以讓每個partition有5個甚至更多Replica來保證更多的健壯性。
- 外部系統不關心Stateful Service有多少個partition,它們通過partition key來進行調用。Partition Key和具體的對應Partition之間由Service Fabric的底層Micro Service進行解析。例如在你的業務中,你可能有幾百萬用戶,但是只設置5個partition。當調用購物車Stateful Service時,外部系統只需要告知:用戶ID(partition key),保存的數據。這個請求會自動根據用戶ID及hash算法固定映射到5個partition中的一個。
- Stateful Service的數據操作支持事務(Transaction)。因此你可以在失敗時回滾(Rollback)
希望以上的介紹可以幫助大家更好的理解Stateful Service。
我們會在后面的章節中介紹Stateful Service的代碼示例。