5 張圖,帶你瞭解微服務架構治理
導讀
隨着公司業務規模的擴大,越來越多的公司選擇了從單體架構轉向微服務架構,將單體應用拆分成多個微服務更適合 “較大” 規模的業務。拆分成微服務後,各服務所負責的業務獨立性更強,管理更方便,代碼衝突更少,版本迭代更快,更能推動業務快速向前發展。
但是微服務化也帶來了新的問題,在單體應用中所有的一切都發生在同一個進程內,業務間交互僅僅是方法間的調用,而拆分成微服務後,各業務間的交互就要通過 rpc 調用來進行,系統變得更爲複雜,這就需要就引入服務治理的概念來對各服務及服務間的交互進行管理,例如:服務註冊與發現、監控、鑑權 & 限流等。
本文從轉轉公司的服務治理實踐出發,帶領讀者揭開服務治理的神祕面紗。
1 整體架構
服務管理平臺與 rpc 框架交互
轉轉服務管理平臺是集服務註冊與發現、配置中心、監控中心、報警、鑑權 & 限流於一體的綜合性服務治理平臺,rpc 框架與服務管理平臺通過 sdk 進行交互。
當服務方啓動時會向管理平臺進行節點註冊,並且向服務管理平臺訂閱調用關係用於調用鑑權、限流等功能。而訂閱該服務方的調用方將收到服務方節點上線、下線事件通知,並重新通過 sdk 拉取服務方的節點列表。
在進行調用時,調用方和服務方都通過 sdk 向服務管理平臺上報調用耗時、超時、異常、耗時分佈、top 百分位等指標。
同時服務管理平臺還具有配置中心的功能,調用方可以通過服務管理平臺配置 rpc 調用相關的參數,例如超時時間、序列化協議等參數,修改後將實時生效。
2 服務註冊與發現
2.1 AP 模型還是 CP 模型
註冊中心爲了高可用,往往會有多個節點,在分佈式系統 CAP 理論中,不可能同時滿足一致性(Consistency)、可用性(Availability)和分區容錯性(Partition tolerance),往往我們會在 AP 和 CP 之間做出選擇設計我們的系統。典型的註冊中心如 zookeeper、etcd 是 CP 模型,而 eureka 是 AP 模型,nacos 既可以工作在 CP 模式下也可以工作在 AP 模式下。
我們模擬一種場景來看看註冊中心應該是 CP 還是 AP 系統。現有註冊中心 R1 和 R2,調用方 C1 和 C2,C1 和 R1 建立長連接,C2 和 R2 建立長連接。
-
服務方 S1 註冊到 R1 上,R1 通知 C1 S1 的上線事件,再通知 R2 S1 的上線事件,而 R2 又將 S1 的上線事件通知到 C2,此時 C1 和 C2 都獲取到了 S1 的上線事件,C1 和 C2 都可以調用到 S1 節點。
-
又有服務方 S2 註冊到 R2 上,R2 通知 C2 S2 的上線事件,再通知 R1 S1 的上線事件,此時發生了異常導致 R2 未能通知到 R1 S2 的上線事件,顯然 C1 也未能得到 S2 的上線事件。C1 只能調用 S1 節點,而 C2 可以調用 S1 和 S2 節點。
-
我們看到此時出現了不一致性,如果是 CP 系統,在解決不一致性問題之前是不能進行下一步操作的,也就是說不能有新的節點註冊上來,此時註冊功能已經不可用了。而仔細思考一下,這種情況下 rpc 調用還能正常進行嗎,答案是肯定的。即使出現不一致性,我們也是可以容忍的,所以註冊中心應該是一個 AP 系統。
-
出現了上述不一致問題怎麼解決呢?我們在服務管理平臺 sdk 中設置了定時任務,在未收到節點上線 / 下線通知時,仍然定時拉取最新的節點列表,以達到最終一致性。
結論:註冊中心應該設計爲 AP 系統,中間短暫的不一致是可以容忍的,只要在短時間內達到最終一致性即可,參考:阿里巴巴爲什麼不用 ZooKeeper 做服務發現 [1]。
2.2 節點分組
當服務方有多個調用方,且調用方重要性等級不一樣時,我們需要提供服務方節點隔離能力,即對服務方節點進行分組,不同的分組提供給不同的調用方使用。
例如服務方 A 有節點 A-S1、A-S2、A-S3、A-S4,有調用方 B、C 和 D,B 重要性遠高於 C 和 D,我們期望對 B 提供更穩定的服務,就可以將 A-S1、A-S2、A-S3、A-S4 進行分組,例如:A-S1、A-S2 分到 “服務 B 專用” 組供服務 B 調用,而 A-S3、A-S4 在 “默認組” 供服務 C 和 D 調用,如下圖所示:
2.3 灰度發現
灰度發現功能是指讓某些調用方發現服務方的某些指定節點,一般的用途爲規劃一條固定的調用鏈路做灰度驗證。如下圖所示,有服務 A、B、C、D,某次需求修改了服務 B、C、D,服務 B、C、D 從 v1 版本升級到了 v2 版本,而且 B-v2 依賴 C-v2,C-v2 依賴 D-v2。在沒有灰度發現功能時,需要將 D 全量升級至 v2,再將 C 全量升級至 v2,最後將 B 全量升級至 v2,如新版本出現 bug,回滾耗時長、損失大。
使用灰度發現功能可僅部署 B-v2、C-v2、D-v2 各一個節點,B-v2 只能發現 C-v2 節點,C-v2 只能發現 D-v2 節點。再配合權重功能將 B-v2 的權重調低,就可以小流量驗證本次需求的正確性,即使出現問題,只需在管理平臺操作將 B-v2 節點移出分組或權重調爲零,無須回滾,可保留現場排查問題,損失微小。
3 配置中心
在 rpc 調用過程中有一系列參數是用戶可以配置的,如 tcp 連接超時時間、請求超時時間(服務級 & 函數級)、序列化協議、rpc 協議版本等。
例如在版本迭代過程中某些方法的耗時增長,上線後需要調用方調整方法超時時間,如果將超時時間寫在調用方代碼中,將調用方重新上線是不太現實的,此時就需要參數熱更新功能。轉轉管理平臺支持 rpc 參數的下發,配合 rpc 框架支持 rpc 參數的熱更新功能,可實現平臺參數調整服務實時生效。
4 監控中心
監控是服務治理中至關重要的一環,面對服務數量小則幾百、多則成千上萬的場景,再加上各服務間的調用關係,共同組成一張龐大的微服務網絡,完善的監控設施是我們洞察這張網的火眼金睛。監控一般包括調用量、異常量、耗時、耗時分佈、耗時百分位等。
監控中的難點在於,如此龐大的數據量如何上報、存儲與查詢的問題。轉轉的解決方案是針對常用查詢維度提前對數據進行多階段聚合計算,以提升查詢效率。
4.1 sdk 聚合
在管理平臺 sdk 中,對調用數據的總耗時、平均耗時、最大耗時、耗時百分位、耗時分佈等進行提前計算,並以分鐘爲維度進行上報,大大減少監控數據上報量,節省帶寬,減少資源佔用。
4.2 後端存儲前聚合
sdk 上報的數據中僅包含當前節點的監控數據,如將這些數據直接存儲,那麼查詢服務級監控數據時再進行實時聚合計算是不太現實的,龐大的數據量將直接導致數據庫不可用。
對此我們以各個查詢維度在數據存儲之前再次進行聚合,例如 sdk 上報的原始數據爲<C,CIP,S,SIP,Data>
,我們期待以<C>
、<S>
、<C,S>
等維度進行查詢,那麼就根據 sdk 上報的原始數據在存儲前以這些維度進行聚合計算,直接存儲計算後的結果。如此以來可實現毫秒級監控數據查詢。
5 鑑權 & 限流
鑑權是指服務間的調用權限控制,限流是指服務間的調用量控制,轉轉管理平臺具有服務級 & 方法級調用權限及調用量控制能力。
若想實現方法級的調用權限及調用量控制能力,需要有標識來定位唯一的 rpc 方法,我們提出 methodKey 概念來標識唯一的 rpc 方法,具體格式爲:(${ServiceImpl})${ServiceInterface}.$method($parameterTypes)
。例如某 rpc 接口UserService
中有saveUser(User user)
方法,其實現類爲UserServiceImpl
,則該方法的 methodKey 爲(UserServiceImpl)UserService.saveUser(User)
,methodKey 中所使用的類名均爲簡單類名,由 rpc 框架來校驗每個服務中 methodKey 的唯一性。
在服務方啓動時 rpc 框架將暴露出的 rpc 方法列表通過 sdk 上傳至服務管理平臺,在服務進行調用之前需要在服務管理平臺申請對方法的調用權限及調用量配置。並通過 sdk 訂閱其他調用方對本服務的調用關係,做到實時修改生效。
在 rpc 框架中通過 Filter 擴展並結合管理平臺 sdk 即可實現對服務調用的權限校驗及流量控制能力。
6 報警
報警也是服務治理中必不可少的一環,在服務治理中發揮着哨兵的作用。依託管理平臺監控能力,在出現調用異常、超時、限流時及時向服務負責人發出警報。轉轉管理平臺允許用戶對告警進行手動配置,包括告警間隔時間、告警方法、告警的服務方和調用方等。
7 總結
本篇文章從轉轉服務治理的整體架構出發,又分篇介紹了服務治理中主要功能的實現,以便各位讀者對服務治理有簡單的認識。
當然,服務治理的能力並不僅限於文中所述,轉轉的管理平臺也不是完美的,仍然有許多問題需要解決,例如通知機制的高可用問題、一致性問題,監控數據存儲問題等。我們將繼續前行在技術的道路上,生命不息,探索不止。
關於作者
王建新,轉轉架構部資深 Java 工程師,主要負責服務治理、RPC 框架、分佈式調用追蹤、監控系統等,熱衷於技術,有豐富的線上實戰經驗。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/ZEJtThE7bmGAK7yz5Ub6-g