5張圖,帶你了解微服務(wù)架構(gòu)治理
導(dǎo)讀
隨著公司業(yè)務(wù)規(guī)模的擴(kuò)大,越來越多的公司選擇了從單體架構(gòu)轉(zhuǎn)向微服務(wù)架構(gòu),將單體應(yīng)用拆分成多個(gè)微服務(wù)更適合“較大”規(guī)模的業(yè)務(wù)。拆分成微服務(wù)后,各服務(wù)所負(fù)責(zé)的業(yè)務(wù)獨(dú)立性更強(qiáng),管理更方便,代碼沖突更少,版本迭代更快,更能推動(dòng)業(yè)務(wù)快速向前發(fā)展。
但是微服務(wù)化也帶來了新的問題,在單體應(yīng)用中所有的一切都發(fā)生在同一個(gè)進(jìn)程內(nèi),業(yè)務(wù)間交互僅僅是方法間的調(diào)用,而拆分成微服務(wù)后,各業(yè)務(wù)間的交互就要通過rpc調(diào)用來進(jìn)行,系統(tǒng)變得更為復(fù)雜,這就需要就引入服務(wù)治理的概念來對各服務(wù)及服務(wù)間的交互進(jìn)行管理,例如:服務(wù)注冊與發(fā)現(xiàn)、監(jiān)控、鑒權(quán)&限流等。
本文從轉(zhuǎn)轉(zhuǎn)公司的服務(wù)治理實(shí)踐出發(fā),帶領(lǐng)讀者揭開服務(wù)治理的神秘面紗。
1 整體架構(gòu)

轉(zhuǎn)轉(zhuǎn)服務(wù)管理平臺是集服務(wù)注冊與發(fā)現(xiàn)、配置中心、監(jiān)控中心、報(bào)警、鑒權(quán)&限流于一體的綜合性服務(wù)治理平臺,rpc框架與服務(wù)管理平臺通過sdk進(jìn)行交互。
當(dāng)服務(wù)方啟動(dòng)時(shí)會(huì)向管理平臺進(jìn)行節(jié)點(diǎn)注冊,并且向服務(wù)管理平臺訂閱調(diào)用關(guān)系用于調(diào)用鑒權(quán)、限流等功能。而訂閱該服務(wù)方的調(diào)用方將收到服務(wù)方節(jié)點(diǎn)上線、下線事件通知,并重新通過sdk拉取服務(wù)方的節(jié)點(diǎn)列表。
在進(jìn)行調(diào)用時(shí),調(diào)用方和服務(wù)方都通過sdk向服務(wù)管理平臺上報(bào)調(diào)用耗時(shí)、超時(shí)、異常、耗時(shí)分布、top百分位等指標(biāo)。
同時(shí)服務(wù)管理平臺還具有配置中心的功能,調(diào)用方可以通過服務(wù)管理平臺配置rpc調(diào)用相關(guān)的參數(shù),例如超時(shí)時(shí)間、序列化協(xié)議等參數(shù),修改后將實(shí)時(shí)生效。
2 服務(wù)注冊與發(fā)現(xiàn)
2.1 AP模型還是CP模型
注冊中心為了高可用,往往會(huì)有多個(gè)節(jié)點(diǎn),在分布式系統(tǒng)CAP理論中,不可能同時(shí)滿足一致性(Consistency)、可用性(Availability)和分區(qū)容錯(cuò)性(Partition tolerance),往往我們會(huì)在AP和CP之間做出選擇設(shè)計(jì)我們的系統(tǒng)。典型的注冊中心如zookeeper、etcd是CP模型,而eureka是AP模型,nacos既可以工作在CP模式下也可以工作在AP模式下。
我們模擬一種場景來看看注冊中心應(yīng)該是CP還是AP系統(tǒng)?,F(xiàn)有注冊中心R1和R2,調(diào)用方C1和C2,C1和R1建立長連接,C2和R2建立長連接。
服務(wù)方S1注冊到R1上,R1通知C1 S1的上線事件,再通知R2 S1的上線事件,而R2又將S1的上線事件通知到C2,此時(shí)C1和C2都獲取到了S1的上線事件,C1和C2都可以調(diào)用到S1節(jié)點(diǎn)。

又有服務(wù)方S2注冊到R2上,R2通知C2 S2的上線事件,再通知R1 S1的上線事件,此時(shí)發(fā)生了異常導(dǎo)致R2未能通知到R1 S2的上線事件,顯然C1也未能得到S2的上線事件。C1只能調(diào)用S1節(jié)點(diǎn),而C2可以調(diào)用S1和S2節(jié)點(diǎn)。

我們看到此時(shí)出現(xiàn)了不一致性,如果是CP系統(tǒng),在解決不一致性問題之前是不能進(jìn)行下一步操作的,也就是說不能有新的節(jié)點(diǎn)注冊上來,此時(shí)注冊功能已經(jīng)不可用了。而仔細(xì)思考一下,這種情況下rpc調(diào)用還能正常進(jìn)行嗎,答案是肯定的。即使出現(xiàn)不一致性,我們也是可以容忍的,所以注冊中心應(yīng)該是一個(gè)AP系統(tǒng)。
出現(xiàn)了上述不一致問題怎么解決呢?我們在服務(wù)管理平臺sdk中設(shè)置了定時(shí)任務(wù),在未收到節(jié)點(diǎn)上線/下線通知時(shí),仍然定時(shí)拉取最新的節(jié)點(diǎn)列表,以達(dá)到最終一致性。
結(jié)論:注冊中心應(yīng)該設(shè)計(jì)為AP系統(tǒng),中間短暫的不一致是可以容忍的,只要在短時(shí)間內(nèi)達(dá)到最終一致性即可,參考:阿里巴巴為什么不用 ZooKeeper 做服務(wù)發(fā)現(xiàn)[1]。
2.2 節(jié)點(diǎn)分組
當(dāng)服務(wù)方有多個(gè)調(diào)用方,且調(diào)用方重要性等級不一樣時(shí),我們需要提供服務(wù)方節(jié)點(diǎn)隔離能力,即對服務(wù)方節(jié)點(diǎn)進(jìn)行分組,不同的分組提供給不同的調(diào)用方使用。
例如服務(wù)方A有節(jié)點(diǎn)A-S1、A-S2、A-S3、A-S4,有調(diào)用方B、C和D,B重要性遠(yuǎn)高于C和D,我們期望對B提供更穩(wěn)定的服務(wù),就可以將A-S1、A-S2、A-S3、A-S4進(jìn)行分組,例如:A-S1、A-S2分到“服務(wù)B專用”組供服務(wù)B調(diào)用,而A-S3、A-S4在“默認(rèn)組”供服務(wù)C和D調(diào)用,如下圖所示:
2.3 灰度發(fā)現(xiàn)
灰度發(fā)現(xiàn)功能是指讓某些調(diào)用方發(fā)現(xiàn)服務(wù)方的某些指定節(jié)點(diǎn),一般的用途為規(guī)劃一條固定的調(diào)用鏈路做灰度驗(yàn)證。如下圖所示,有服務(wù)A、B、C、D,某次需求修改了服務(wù)B、C、D,服務(wù)B、C、D從v1版本升級到了v2版本,而且B-v2依賴C-v2,C-v2依賴D-v2。在沒有灰度發(fā)現(xiàn)功能時(shí),需要將D全量升級至v2,再將C全量升級至v2,最后將B全量升級至v2,如新版本出現(xiàn)bug,回滾耗時(shí)長、損失大。
使用灰度發(fā)現(xiàn)功能可僅部署B(yǎng)-v2、C-v2、D-v2各一個(gè)節(jié)點(diǎn),B-v2只能發(fā)現(xiàn)C-v2節(jié)點(diǎn),C-v2只能發(fā)現(xiàn)D-v2節(jié)點(diǎn)。再配合權(quán)重功能將B-v2的權(quán)重調(diào)低,就可以小流量驗(yàn)證本次需求的正確性,即使出現(xiàn)問題,只需在管理平臺操作將B-v2節(jié)點(diǎn)移出分組或權(quán)重調(diào)為零,無須回滾,可保留現(xiàn)場排查問題,損失微小。
3 配置中心
在rpc調(diào)用過程中有一系列參數(shù)是用戶可以配置的,如tcp連接超時(shí)時(shí)間、請求超時(shí)時(shí)間(服務(wù)級&函數(shù)級)、序列化協(xié)議、rpc協(xié)議版本等。
例如在版本迭代過程中某些方法的耗時(shí)增長,上線后需要調(diào)用方調(diào)整方法超時(shí)時(shí)間,如果將超時(shí)時(shí)間寫在調(diào)用方代碼中,將調(diào)用方重新上線是不太現(xiàn)實(shí)的,此時(shí)就需要參數(shù)熱更新功能。轉(zhuǎn)轉(zhuǎn)管理平臺支持rpc參數(shù)的下發(fā),配合rpc框架支持rpc參數(shù)的熱更新功能,可實(shí)現(xiàn)平臺參數(shù)調(diào)整服務(wù)實(shí)時(shí)生效。
4 監(jiān)控中心
監(jiān)控是服務(wù)治理中至關(guān)重要的一環(huán),面對服務(wù)數(shù)量小則幾百、多則成千上萬的場景,再加上各服務(wù)間的調(diào)用關(guān)系,共同組成一張龐大的微服務(wù)網(wǎng)絡(luò),完善的監(jiān)控設(shè)施是我們洞察這張網(wǎng)的火眼金睛。監(jiān)控一般包括調(diào)用量、異常量、耗時(shí)、耗時(shí)分布、耗時(shí)百分位等。
監(jiān)控中的難點(diǎn)在于,如此龐大的數(shù)據(jù)量如何上報(bào)、存儲(chǔ)與查詢的問題。轉(zhuǎn)轉(zhuǎn)的解決方案是針對常用查詢維度提前對數(shù)據(jù)進(jìn)行多階段聚合計(jì)算,以提升查詢效率。
4.1 sdk聚合
在管理平臺sdk中,對調(diào)用數(shù)據(jù)的總耗時(shí)、平均耗時(shí)、最大耗時(shí)、耗時(shí)百分位、耗時(shí)分布等進(jìn)行提前計(jì)算,并以分鐘為維度進(jìn)行上報(bào),大大減少監(jiān)控?cái)?shù)據(jù)上報(bào)量,節(jié)省帶寬,減少資源占用。
4.2 后端存儲(chǔ)前聚合
sdk上報(bào)的數(shù)據(jù)中僅包含當(dāng)前節(jié)點(diǎn)的監(jiān)控?cái)?shù)據(jù),如將這些數(shù)據(jù)直接存儲(chǔ),那么查詢服務(wù)級監(jiān)控?cái)?shù)據(jù)時(shí)再進(jìn)行實(shí)時(shí)聚合計(jì)算是不太現(xiàn)實(shí)的,龐大的數(shù)據(jù)量將直接導(dǎo)致數(shù)據(jù)庫不可用。
對此我們以各個(gè)查詢維度在數(shù)據(jù)存儲(chǔ)之前再次進(jìn)行聚合,例如sdk上報(bào)的原始數(shù)據(jù)為<C,CIP,S,SIP,Data>,我們期待以<C>、<S>、<C,S>等維度進(jìn)行查詢,那么就根據(jù)sdk上報(bào)的原始數(shù)據(jù)在存儲(chǔ)前以這些維度進(jìn)行聚合計(jì)算,直接存儲(chǔ)計(jì)算后的結(jié)果。如此以來可實(shí)現(xiàn)毫秒級監(jiān)控?cái)?shù)據(jù)查詢。
5 鑒權(quán)&限流
鑒權(quán)是指服務(wù)間的調(diào)用權(quán)限控制,限流是指服務(wù)間的調(diào)用量控制,轉(zhuǎn)轉(zhuǎn)管理平臺具有服務(wù)級&方法級調(diào)用權(quán)限及調(diào)用量控制能力。
若想實(shí)現(xiàn)方法級的調(diào)用權(quán)限及調(diào)用量控制能力,需要有標(biāo)識來定位唯一的rpc方法,我們提出methodKey概念來標(biāo)識唯一的rpc方法,具體格式為:(${ServiceImpl})${ServiceInterface}.$method($parameterTypes)。例如某rpc接口UserService中有saveUser(User user)方法,其實(shí)現(xiàn)類為UserServiceImpl,則該方法的methodKey為(UserServiceImpl)UserService.saveUser(User),methodKey中所使用的類名均為簡單類名,由rpc框架來校驗(yàn)每個(gè)服務(wù)中methodKey的唯一性。
在服務(wù)方啟動(dòng)時(shí)rpc框架將暴露出的rpc方法列表通過sdk上傳至服務(wù)管理平臺,在服務(wù)進(jìn)行調(diào)用之前需要在服務(wù)管理平臺申請對方法的調(diào)用權(quán)限及調(diào)用量配置。并通過sdk訂閱其他調(diào)用方對本服務(wù)的調(diào)用關(guān)系,做到實(shí)時(shí)修改生效。
在rpc框架中通過Filter擴(kuò)展并結(jié)合管理平臺sdk即可實(shí)現(xiàn)對服務(wù)調(diào)用的權(quán)限校驗(yàn)及流量控制能力。
6 報(bào)警
報(bào)警也是服務(wù)治理中必不可少的一環(huán),在服務(wù)治理中發(fā)揮著哨兵的作用。依托管理平臺監(jiān)控能力,在出現(xiàn)調(diào)用異常、超時(shí)、限流時(shí)及時(shí)向服務(wù)負(fù)責(zé)人發(fā)出警報(bào)。轉(zhuǎn)轉(zhuǎn)管理平臺允許用戶對告警進(jìn)行手動(dòng)配置,包括告警間隔時(shí)間、告警方法、告警的服務(wù)方和調(diào)用方等。
7 總結(jié)
本篇文章從轉(zhuǎn)轉(zhuǎn)服務(wù)治理的整體架構(gòu)出發(fā),又分篇介紹了服務(wù)治理中主要功能的實(shí)現(xiàn),以便各位讀者對服務(wù)治理有簡單的認(rèn)識。
當(dāng)然,服務(wù)治理的能力并不僅限于文中所述,轉(zhuǎn)轉(zhuǎn)的管理平臺也不是完美的,仍然有許多問題需要解決,例如通知機(jī)制的高可用問題、一致性問題,監(jiān)控?cái)?shù)據(jù)存儲(chǔ)問題等。我們將繼續(xù)前行在技術(shù)的道路上,生命不息,探索不止。
關(guān)于作者
王建新,轉(zhuǎn)轉(zhuǎn)架構(gòu)部資深Java工程師,主要負(fù)責(zé)服務(wù)治理、RPC框架、分布式調(diào)用追蹤、監(jiān)控系統(tǒng)等,熱衷于技術(shù),有豐富的線上實(shí)戰(zhàn)經(jīng)驗(yàn)。
參考資料
阿里巴巴為什么不用 ZooKeeper 做服務(wù)發(fā)現(xiàn): https://github.com/markdown-it/markdown-it/issues/410
往期推薦
如果你覺得這篇文章不錯(cuò),那么,下篇通常會(huì)更好。添加微信好友,可備注“加群”(微信號:zhuan2quan)。
和花一輩子都看不清的人,
注定是截然不同的搬磚生涯。



