文章整理:加米谷大數(shù)據(jù)
一、MNS 1.0 簡(jiǎn)介
圖 1 MNS 1.0 架構(gòu)
從架構(gòu)上看,MNS 1.0 主要分為三層:首先是嵌入業(yè)務(wù)內(nèi)部的 SDK,用作業(yè)務(wù)自定義調(diào)用;然后是駐守在每個(gè)機(jī)器上的 SgAgent,以代理的方式將一些易變的、消耗性能的計(jì)算邏輯與業(yè)務(wù)進(jìn)程分離開(kāi)來(lái),從而降低 SDK 對(duì)業(yè)務(wù)的侵入,減少策略變動(dòng)對(duì)業(yè)務(wù)的干擾;遠(yuǎn)端是集中式的組件,包括健康檢查模塊 Scanner,鑒權(quán)緩存模塊 MNSC,以及基于 ZooKeeper(以下簡(jiǎn)稱 ZK)打造的一致性組件 MNS-ZK,作為通知和存儲(chǔ)模塊。在層級(jí)之間設(shè)立多級(jí)緩存,利用“邊緣計(jì)算”思想拆分邏輯,簡(jiǎn)化數(shù)據(jù),盡量將路由分配等工作均攤到端上,從而降低中心組件負(fù)載。
更多詳情大家可參考《美團(tuán)大規(guī)模微服務(wù)通信框架及治理體系 OCTO 核心組件開(kāi)源》一文中的 OCTO-NS 部分。
在體量方面,MNS 1.0 已經(jīng)接入了美團(tuán)所有的在線應(yīng)用,涉及上萬(wàn)項(xiàng)服務(wù)、數(shù)十萬(wàn)個(gè)節(jié)點(diǎn),并覆蓋了美團(tuán)所有的業(yè)務(wù)線,日均調(diào)用達(dá)萬(wàn)億級(jí)別,目前我們已將其開(kāi)源。
總的來(lái)講,作為公司級(jí)核心服務(wù)治理組件,MNS 1.0 在架構(gòu)上帶有明顯的 CP 屬性,在保持架構(gòu)簡(jiǎn)潔、流程清晰的同時(shí),還支持了業(yè)務(wù)大量迭代的需求,較好地幫助公司業(yè)務(wù)實(shí)現(xiàn)了服務(wù)化、標(biāo)準(zhǔn)化的目標(biāo)。
二、MNS 1.0 遇到的問(wèn)題和挑戰(zhàn)
圖 2 近三年美團(tuán)業(yè)務(wù)增長(zhǎng)數(shù)據(jù)
但是隨著美團(tuán)業(yè)務(wù)的快速增長(zhǎng),公司的服務(wù)數(shù)、節(jié)點(diǎn)數(shù)、服務(wù)信息量、服務(wù)變動(dòng)頻次等維度都在快速增長(zhǎng),有些服務(wù)甚至呈現(xiàn)出跨數(shù)量級(jí)的增長(zhǎng)。在這樣的情況下,命名服務(wù)也面臨著一些新的問(wèn)題和挑戰(zhàn):
- 可用性 :公司業(yè)務(wù)持續(xù)高速增長(zhǎng),很多都需要進(jìn)行跨地域的部署。在 MNS 1.0 架構(gòu)下,地域之間的專(zhuān)線如果斷連,會(huì)發(fā)生一個(gè)地域命名服務(wù)整體不可用的情況;其次,強(qiáng)一致組件存在單點(diǎn)問(wèn)題,Leader 出現(xiàn)故障,整個(gè)集群中斷服務(wù);另外,在多客戶端和大數(shù)據(jù)傳輸?shù)拿?wù)場(chǎng)景下,CP 系統(tǒng)恢復(fù)困難,RTO 達(dá)到小時(shí)級(jí)別。MNS 1.0 曾經(jīng)出現(xiàn)過(guò)后端集中式組件單機(jī)連接超過(guò)十萬(wàn)且活躍鏈接數(shù)過(guò)半的情況,出現(xiàn)問(wèn)題之后,現(xiàn)場(chǎng)恢復(fù)的負(fù)荷可想而知,這些都給命名系統(tǒng)的可用性帶來(lái)很大的風(fēng)險(xiǎn)。
- 擴(kuò)展性 :相對(duì)于需要支持的業(yè)務(wù)數(shù)量,MNS 1.0 整體平行擴(kuò)展能力不足。MNS-ZK 的單集群規(guī)模上限不超過(guò) 300(實(shí)際只能達(dá)到 250 左右,這與 ZooKeeper 內(nèi)部的 myid 等機(jī)制有關(guān)),否則同步性能會(huì)急劇惡化;其次,集群寫(xiě)入不可擴(kuò)展,參與寫(xiě)入節(jié)點(diǎn)越多性能越差;另外,服務(wù)信息快照在固定的時(shí)間片內(nèi)持續(xù)增長(zhǎng),增加 IO 壓力的同時(shí)也延長(zhǎng)了遷移的同步時(shí)間。而擴(kuò)展性上的短板,導(dǎo)致 MNS 1.0 難以應(yīng)對(duì)突發(fā)的流量洪峰,易出現(xiàn)“雪崩”。
- 性能 :寫(xiě)入操作受 CP 屬性限制,串行性能較低。MNS-ZK 整體到 7000 左右的寫(xiě)量就已接近上限。其次,在熱點(diǎn)服務(wù)場(chǎng)景下,數(shù)據(jù)分發(fā)較慢,這跟數(shù)據(jù)粒度較粗也有一定關(guān)系。而數(shù)據(jù)粒度粗、量大,也會(huì)在組件間傳輸消息時(shí),導(dǎo)致臨時(shí)對(duì)象頻繁生成,引起 GC。另外,MNS 1.0 的后端集群負(fù)載還存在均衡性問(wèn)題,一是因?yàn)樵軜?gòu)中缺乏集中管控服務(wù),無(wú)法進(jìn)行動(dòng)態(tài)的集群與數(shù)據(jù)拆分伸縮,二是因?yàn)閺?qiáng)一致屬性下,集群節(jié)點(diǎn)間基于 Session 的遷移現(xiàn)場(chǎng)較重,很容易因一個(gè)節(jié)點(diǎn)掛掉而引起連鎖反應(yīng)。
圖 3 命名服務(wù)應(yīng)該是 AP 系統(tǒng)
從可用性、擴(kuò)展性、性能等三個(gè)方面,MNS 1.0 暴露出很多的問(wèn)題,究其根源,原來(lái)的命名服務(wù)作為一個(gè) CP 系統(tǒng),為獲得“數(shù)據(jù)一致性”而犧牲了部分情況下的可用性。其實(shí),對(duì)于命名服務(wù)而言,一致性并沒(méi)有這么重要,最多是調(diào)用方在一定時(shí)間內(nèi)調(diào)多了或調(diào)漏了服務(wù)方而已,這個(gè)后果在不可靠網(wǎng)絡(luò)的大前提下,即使命名服務(wù)沒(méi)有出現(xiàn)問(wèn)題,也可能經(jīng)常會(huì)出現(xiàn)。借助端的自我檢查調(diào)整機(jī)制,其影響可以說(shuō)微乎其微。而另一方面,如果是一個(gè)機(jī)房或一個(gè)地域的調(diào)用方和服務(wù)方?jīng)]有問(wèn)題,但是因?yàn)檫@個(gè)區(qū)域和命名服務(wù)主集群斷開(kāi)了鏈接,從而導(dǎo)致本域內(nèi)不能互調(diào),這個(gè)就顯得不太合理了。
所以總結(jié)一下,我們認(rèn)為, 命名服務(wù)的本質(zhì)是建立和增強(qiáng)服務(wù)本身的連通性,而不是主動(dòng)去破壞連通性 。命名服務(wù)本質(zhì)上應(yīng)該是一個(gè) AP 系統(tǒng)。
其實(shí),業(yè)界對(duì)命名服務(wù) AP/CP 模式都有相應(yīng)實(shí)現(xiàn)和應(yīng)用,很多企業(yè)使用 CP 模式,原因可能有以下幾點(diǎn):
- 架構(gòu)行為簡(jiǎn)單 :CP 系統(tǒng)在出現(xiàn)分區(qū)時(shí)行為比較簡(jiǎn)單,冷凍處理,粗暴但相對(duì)不容易出錯(cuò)。
- 啟動(dòng)門(mén)檻低 :一些成熟的開(kāi)源一致性組件,比如 ZK、etcd 都是 CP 系統(tǒng),能夠開(kāi)箱即用,在數(shù)據(jù)規(guī)??煽氐那闆r下,基本能夠滿足企業(yè)的需求。
另外,我們了解到,一些公司使用特殊的方式弱化了這個(gè)問(wèn)題,比如將 CP 系統(tǒng)進(jìn)一步拆分到更小的域中(比如一個(gè) IDC),縮小分區(qū)的粒度,而全局有多個(gè) CP 系統(tǒng)自治。當(dāng)然,這個(gè)可能跟調(diào)用方服務(wù)方的跨度限制或者說(shuō)調(diào)用配套部署有關(guān)系,但也有可能帶來(lái)更復(fù)雜的問(wèn)題(比如 CP 系統(tǒng)之間的數(shù)據(jù)同步),這里就不做詳細(xì)的討論了。
除去 MNS 1.0 本身的架構(gòu)缺陷,我們還需要面臨另一個(gè)問(wèn)題,當(dāng)初在項(xiàng)目啟動(dòng)時(shí),云原生尚處于起步階段,而如今,一些基于云原生理念興起的網(wǎng)絡(luò)基礎(chǔ)設(shè)施,尤其是 Service Mesh 在美團(tuán)快速發(fā)展,也需要 MNS 進(jìn)行改造去適配新的流量通道和管控組件,這也是此次 MNS 2.0 演進(jìn)的目標(biāo)之一。
綜上,我們以 AP 化、Mesh 化為主要目標(biāo),正式開(kāi)始了從 MNS 1.0 向 MNS 2.0 的演進(jìn)。
三、MNS 2.0
1. 整體架構(gòu)
圖 4 MNS 2.0 整體架構(gòu)
MNS 2.0 的整體架構(gòu)自上而下主要分為四層:
- 業(yè)務(wù)系統(tǒng)層 :這一層與 MNS 1.0 架構(gòu)類(lèi)似,依然是嵌入到業(yè)務(wù)系統(tǒng)中的 SDK 或框架,但是不再感知服務(wù)列表和路由計(jì)算,從而變得更加的輕薄。
- 代理接入層 :這一層主要變化是加入了 Service Mesh 的 Sidecar 和 MNS-API。前者將命名服務(wù)的部分鏈路接入 Mesh;后者為 MNS 增加了更豐富的 HTTP 調(diào)用,幫助一些沒(méi)有使用 SDK 或框架的業(yè)務(wù)快速接入到命名服務(wù)。整個(gè)代理接入層的改造使得 MNS 對(duì)接入業(yè)務(wù)更加親和。
- 控制服務(wù)層 :新增注冊(cè)中心控制服務(wù),這也是 MNS 2.0 的核心。主要分為以下三個(gè)模塊:a. 網(wǎng)關(guān)管控模塊 :提供集中式的鑒權(quán)、限流 / 熔斷、統(tǒng)計(jì)等 SOA 服務(wù)化的管控能力,同時(shí)避免海量代理組件直連存儲(chǔ)層。b. 數(shù)據(jù)分發(fā)模塊 :數(shù)據(jù)的通道,包括注冊(cè)數(shù)據(jù)的上傳、訂閱數(shù)據(jù)的下發(fā),可進(jìn)行精細(xì)化數(shù)據(jù)拆分和平行擴(kuò)展來(lái)適配熱點(diǎn)服務(wù)。c. 變更捕獲模塊 :服務(wù)注冊(cè)發(fā)現(xiàn)的審計(jì),包括對(duì)第三方系統(tǒng)進(jìn)行事件通知和回調(diào),支持多元化的服務(wù)數(shù)據(jù)營(yíng)運(yùn)需求。另外,控制服務(wù)層還包括全鏈路 SLA 監(jiān)控等新的子模塊,以及健康檢查 Scanner 這樣的傳統(tǒng) MNS 組件。
- 數(shù)據(jù)存儲(chǔ)層 :我們進(jìn)一步豐富了命名服務(wù)的存儲(chǔ)和分發(fā)介質(zhì),提高了數(shù)據(jù)層的整體性能。主力存儲(chǔ)使用 K/V 存儲(chǔ)系統(tǒng)(美團(tuán) Cellar 系統(tǒng))替代 MNS-ZK,有效地提高了數(shù)據(jù)的吞吐能力,支持網(wǎng)絡(luò)分區(qū)后的數(shù)據(jù)讀寫(xiě)以及宕機(jī)災(zāi)備,同時(shí)保留 ZK 做一些輕量級(jí)的 Notify 功能。新增的關(guān)系型數(shù)據(jù)庫(kù)和消息隊(duì)列(美團(tuán) Mafka 系統(tǒng)),配合控制層的變更捕獲模塊,提供更方便的數(shù)據(jù)挖掘結(jié)構(gòu)和外部扇出。
- 旁路于上面 4 層的是外部營(yíng)運(yùn)設(shè)施,主要是業(yè)務(wù)端的可視化 Portal,用戶可以在上面對(duì)自身服務(wù)進(jìn)行監(jiān)控和操作,美團(tuán)的基礎(chǔ)研發(fā)部門(mén)也可以在上面進(jìn)行一些集中式的管控。
綜上所述,MNS 2.0 整體架構(gòu)在兼容 1.0 的前提下,重點(diǎn)變化是: 新增了控制服務(wù)層并對(duì)底層存儲(chǔ)介質(zhì)進(jìn)行拆解 。下面,我們來(lái)看一下服務(wù)注冊(cè)發(fā)現(xiàn)功能在 MNS 2.0 中的實(shí)現(xiàn)流程:
圖 5 MNS 2.0 中的服務(wù)注冊(cè)發(fā)現(xiàn)流程
- 服務(wù)注冊(cè) :代理接入層透?jìng)鳂I(yè)務(wù)注冊(cè)請(qǐng)求,經(jīng)過(guò)控制服務(wù)層的管控模塊(Gateway)一系列 SOA 和審計(jì)流程后,寫(xiě)入注冊(cè)數(shù)據(jù)到存儲(chǔ)層。
- 數(shù)據(jù)感知 :控制服務(wù)監(jiān)聽(tīng)數(shù)據(jù)變動(dòng),服務(wù)注冊(cè)寫(xiě)入新信息后,分發(fā)模塊(Delivery)更新內(nèi)存中的緩存,數(shù)據(jù)流經(jīng)過(guò)捕獲模塊(CDC)將注冊(cè)信息關(guān)系化后存儲(chǔ)到 DB。
- 服務(wù)發(fā)現(xiàn) :代理層請(qǐng)求經(jīng)過(guò)控制服務(wù)的管控模塊(Gateway)效驗(yàn)后,從分發(fā)模塊(Delivery)的緩存中批量獲取服務(wù)端注冊(cè)信息。Cache Miss 場(chǎng)景時(shí)從存儲(chǔ)層讀取數(shù)據(jù)。
- 外部交互層 :外部系統(tǒng)當(dāng)下通過(guò)代理層接入整個(gè) MNS 體系,避免直連存儲(chǔ)帶來(lái)的各類(lèi)風(fēng)險(xiǎn)問(wèn)題。未來(lái),營(yíng)運(yùn)平臺(tái)可直接使用準(zhǔn)實(shí)時(shí) DB 數(shù)據(jù),以 OLAP 方式進(jìn)行關(guān)系化數(shù)據(jù)的分析。
接下來(lái),我們一起來(lái)看下 MNS2.0 的主要演進(jìn)成果。
2. 演進(jìn)成果
2.1 流量洪峰 & 平行擴(kuò)展
流量洪峰對(duì)于不同領(lǐng)域而言有不同的時(shí)段。對(duì)于 O2O 領(lǐng)域比如美團(tuán)來(lái)說(shuō),就是每天中午的外賣(mài)高峰期,然后每天晚上也會(huì)有酒旅入住的高峰等等。當(dāng)然,基于其它的業(yè)務(wù)場(chǎng)景,也會(huì)有不同的高峰來(lái)源。比如通過(guò)“借勢(shì)營(yíng)銷(xiāo)”等運(yùn)營(yíng)手段,帶來(lái)的高峰量可能會(huì)遠(yuǎn)超預(yù)期,進(jìn)而對(duì)服務(wù)造成巨大的壓力。
圖 6 流量洪峰
MNS 1.0 受制于 MNS-ZK 集群數(shù)量上限和強(qiáng)一致性的要求,無(wú)法做到快速、平行擴(kuò)展。MNS 2.0 的數(shù)據(jù)存儲(chǔ)層重心是保證數(shù)據(jù)安全讀寫(xiě)和分布式協(xié)調(diào),在擴(kuò)展能力層面不應(yīng)該對(duì)其有太多的要求。MNS 2.0 的平行擴(kuò)展能力主要體現(xiàn)在控制服務(wù)層,其具體功能包括以下兩個(gè)方面:
集群分片 :控制服務(wù)提供全量注冊(cè)數(shù)據(jù)的 分片能力 ,解決命名服務(wù)單獨(dú)進(jìn)行大集群部署時(shí)不能進(jìn)行業(yè)務(wù)線隔離的風(fēng)險(xiǎn)。MNS-Control 網(wǎng)關(guān)模塊分為 Master 和 Shard 等兩類(lèi)角色,協(xié)作提供大集群分片能力。
- Master :維護(hù)服務(wù)注冊(cè)信息與各個(gè)分片集群(Shard)的映射關(guān)系,向代理層組件提供該類(lèi) Meta 數(shù)據(jù)。Master 接收各個(gè) Shard 集群事件,新增、清理 Shard 中維護(hù)的注冊(cè)信息。
- Shard :數(shù)據(jù)分片自治向代理組件提供服務(wù)注冊(cè) / 發(fā)現(xiàn)功能,實(shí)現(xiàn)按業(yè)務(wù)線隔離命名服務(wù),同時(shí)按照 Master 發(fā)出的指令,調(diào)整維護(hù)的注冊(cè)信息內(nèi)容。
- Services :業(yè)務(wù)服務(wù)通過(guò)代理組件接入 MNS,代理組件啟動(dòng)時(shí)通過(guò)與 Master 的交互,獲知?dú)w屬的 Shard 集群信息以及 Fallback 處理措施。此后 Agent 只與業(yè)務(wù)線 Shard 進(jìn)行命名數(shù)據(jù)交互,直到 Shard 集群不可用,重新執(zhí)行“自發(fā)現(xiàn)”流程。
- Fallback 措施 :設(shè)置一個(gè)提供全量服務(wù)信息的默認(rèn) Shard 集群,當(dāng)業(yè)務(wù)線 Shard 異常時(shí)。一方面,Agent 重啟“自發(fā)現(xiàn)”流程,同時(shí)將命名請(qǐng)求重定向到默認(rèn)的 Shard 集群,直到業(yè)務(wù)線 Shard 恢復(fù)后,流量再切回。
圖 7 控制服務(wù)數(shù)據(jù)分片示意圖
網(wǎng)絡(luò)分區(qū)可用 :MNS 1.0 階段,網(wǎng)絡(luò)分區(qū)對(duì)可用性的影響巨大,分區(qū)后 MNS-ZK 直接拒絕服務(wù)。新架構(gòu)將存儲(chǔ)遷移到 KV 系統(tǒng)后,在網(wǎng)絡(luò)專(zhuān)線抖動(dòng)等極端情況下,各區(qū)域依然能正常提供數(shù)據(jù)讀取功能。同時(shí),我們與公司存儲(chǔ)團(tuán)隊(duì)共建 C++ SDK 的地域就近讀寫(xiě)功能。一方面,提高跨域服務(wù)注冊(cè)發(fā)現(xiàn)的性能,另一方面,實(shí)現(xiàn)了網(wǎng)絡(luò)分區(qū)后,各區(qū)域內(nèi)命名服務(wù)可讀、可寫(xiě)的目標(biāo),提高了系統(tǒng)的可用性,整個(gè)命名服務(wù)對(duì)網(wǎng)絡(luò)的敏感度降低。
圖 8 命名服務(wù)的平行擴(kuò)展
目前,控制服務(wù)層在平行擴(kuò)縮容時(shí)間和集群原地恢復(fù)時(shí)間等方面,都達(dá)到了分鐘級(jí),集群也沒(méi)有節(jié)點(diǎn)上限,從而能夠有效應(yīng)對(duì)突發(fā)的流量,防止服務(wù)出現(xiàn)“雪崩”。
2.2 推送風(fēng)暴 & 性能提升
另一個(gè)典型的場(chǎng)景是推送“風(fēng)暴”,在服務(wù)集中發(fā)布、出現(xiàn)網(wǎng)絡(luò)抖動(dòng)等情況下,會(huì)導(dǎo)致命名服務(wù)出現(xiàn) " 一橫一縱 " 兩種類(lèi)型的放大效應(yīng):橫向是“關(guān)注放大”,類(lèi)似于社交網(wǎng)絡(luò)中某大 V 消息需要分發(fā)給眾多的粉絲,服務(wù)越核心,放大的效果越明顯??v向是“級(jí)聯(lián)放大”,命名服務(wù)的上下游會(huì)逐級(jí)進(jìn)行拷貝發(fā)送,甚至一級(jí)上下游會(huì)針對(duì)一個(gè)消息有多次的交互(Notify+Pull)。
圖 9 命名服務(wù)領(lǐng)域的消息放大現(xiàn)象
“關(guān)注放大”和“級(jí)聯(lián)放大”本身都是無(wú)法避免的,這是由系統(tǒng)屬性決定,而我們能做的就是從兩方面去平滑其帶來(lái)的影響:
正面提升核心模塊性能,增強(qiáng)吞吐、降低延遲
- 結(jié)構(gòu)化聚合注冊(cè)信息 :控制服務(wù)的數(shù)據(jù)分發(fā)模塊,在內(nèi)存中存儲(chǔ)結(jié)構(gòu)化的服務(wù)注冊(cè)信息,提供批量數(shù)據(jù)的讀取能力;降低多次網(wǎng)絡(luò) RTT 傳輸單個(gè)數(shù)據(jù)以及數(shù)據(jù)結(jié)構(gòu)轉(zhuǎn)化帶來(lái)的高耗時(shí)。
- 高并發(fā)的吞吐能力 :控制服務(wù)通過(guò)無(wú)鎖編程處理關(guān)鍵路徑的競(jìng)爭(zhēng)問(wèn)題,借助應(yīng)用側(cè)協(xié)程機(jī)制,提供高并發(fā)、低延遲的數(shù)據(jù)分發(fā)功能。
- 與存儲(chǔ)團(tuán)隊(duì)共建,實(shí)現(xiàn) KV 系統(tǒng)就近區(qū)域讀寫(xiě),提高命名服務(wù)的服務(wù)注冊(cè)(數(shù)據(jù)寫(xiě)入)性能。
另外,包括前面提到的控制服務(wù)集群的平行擴(kuò)展能力,其實(shí)也是整體性能提升的一種方式。
側(cè)面疏通,區(qū)分冷熱數(shù)據(jù),降低推送的數(shù)據(jù)量,提高效能
自然界中普遍存在“80/20 法則”,命名服務(wù)也不例外。服務(wù)注冊(cè)信息的結(jié)構(gòu)體中元素,80% 的改動(dòng)主要是針對(duì) 20% 的成員,比較典型的就是服務(wù)狀態(tài)。因此,我們將單個(gè)整塊的服務(wù)信息結(jié)構(gòu)體,拆分為多個(gè)較小的結(jié)構(gòu)體分離存儲(chǔ);當(dāng)數(shù)據(jù)變動(dòng)發(fā)生時(shí),按需分發(fā)對(duì)應(yīng)的新結(jié)構(gòu)體,能夠降低推送的數(shù)據(jù)量,有效減少網(wǎng)絡(luò)帶寬的占用,避免代理組件重復(fù)計(jì)算引起的 CPU 開(kāi)銷(xiāo),數(shù)據(jù)結(jié)構(gòu)變小后,內(nèi)存開(kāi)銷(xiāo)也得到顯著降低。
那是否需要做到完全的“按需更新”,僅推送數(shù)據(jù)結(jié)構(gòu)中變動(dòng)的元素呢?我們認(rèn)為,完全的“按需更新”需要非常精細(xì)的架構(gòu)設(shè)計(jì),并會(huì)引入額外的計(jì)算存儲(chǔ)開(kāi)銷(xiāo)。比如,我們需要將變動(dòng)成員分開(kāi)存儲(chǔ)以實(shí)現(xiàn)細(xì)粒度 Watcher,或用專(zhuān)門(mén)服務(wù)識(shí)別變動(dòng)元素然后進(jìn)行推送。
同時(shí),還要保證不同成員變動(dòng)時(shí),每次都要推送成功,否則就會(huì)出現(xiàn)不一致等問(wèn)題。在組件計(jì)算邏輯所需的數(shù)據(jù)發(fā)生變化時(shí),也會(huì)帶來(lái)更多的改動(dòng)。在命名服務(wù)這樣的大型分布式系統(tǒng)中,“復(fù)雜”、“易變”就意味著穩(wěn)定性的下降和風(fēng)險(xiǎn)的上升。所以根據(jù)“80/20 法則”,我們進(jìn)行尺度合理的冷熱數(shù)據(jù)分離,這是在方案有效性和風(fēng)險(xiǎn)性上進(jìn)行權(quán)衡后的結(jié)果。
圖 10 冷熱數(shù)據(jù)分拆推送
經(jīng)過(guò)改造,MNS 2.0 相比 MNS 1.0 的吞吐能力提升 8 倍以上,推送成功率從 96% 提升到 99%+,1K 大小服務(wù)列表服務(wù)發(fā)現(xiàn)的平均耗時(shí),從 10s 降低到 1s,TP999 從 90s 下降到 10s,整體優(yōu)化效果非常明顯。
2.3 融入 Service Mesh
在 MNS 2.0 中,我們將代理服務(wù) SgAgent 部分注冊(cè)發(fā)現(xiàn)功能合并到了 Mesh 數(shù)據(jù)面,其流程如下圖所示:
圖 11 命名服務(wù)與 Service Mesh 的融合
關(guān)于美團(tuán)服務(wù)治理功能與 Service Mesh 結(jié)合的技術(shù)細(xì)節(jié),這部分的內(nèi)容,我們今年會(huì)單獨(dú)做一個(gè)專(zhuān)題來(lái)進(jìn)行分享,感興趣的同學(xué)可以關(guān)注“美團(tuán)技術(shù)團(tuán)隊(duì)”微信公眾號(hào),敬請(qǐng)期待。
2.4 無(wú)損遷移
除了上面說(shuō)到的 MNS 2.0 的這些重點(diǎn)演進(jìn)成果之外,我們還想談一下整個(gè)命名服務(wù)的遷移過(guò)程。像 MNS 這樣涉及多個(gè)組件、部署在公司幾十萬(wàn)個(gè)機(jī)器節(jié)點(diǎn)上、支撐數(shù)萬(wàn)業(yè)務(wù)系統(tǒng)的大規(guī)模分布式系統(tǒng),如何進(jìn)行平滑的數(shù)據(jù)遷移而不中斷業(yè)務(wù)正常服務(wù),甚至不讓業(yè)務(wù)感知到,是 MNS 2.0 設(shè)計(jì)的一個(gè)重點(diǎn)。圍繞業(yè)務(wù)服務(wù)無(wú)感知、具備快速回滾能力、新 / 老體系互備數(shù)據(jù)不丟失等要求,我們?cè)O(shè)計(jì)了如下圖所示的遷移流程:
圖 12 MNS 2.0 的無(wú)損遷移
MNS 2.0 整體以服務(wù)為粒度進(jìn)行遷移操作,設(shè)置標(biāo)志位說(shuō)明服務(wù)所處的狀態(tài),由接入代理層組件識(shí)別該標(biāo)志做出相應(yīng)的處理。標(biāo)志位包括:
- 未遷移標(biāo)志 :服務(wù)注冊(cè) / 發(fā)現(xiàn)走 MNS 1.0 的流程,注冊(cè)信息存儲(chǔ)到重構(gòu)前的 MNS-ZK 中。
- 遷移中標(biāo)志 :服務(wù)注冊(cè)并行走 MNS 1.0 和 MNS 2.0 流程,數(shù)據(jù)同時(shí)寫(xiě)入新舊兩個(gè)地方,服務(wù)發(fā)現(xiàn)執(zhí)行 MNS 2.0 流程。
- 已遷移標(biāo)志 :服務(wù)注冊(cè) / 發(fā)現(xiàn)全部走 MNS 2.0 流程,注冊(cè)信息僅存儲(chǔ)到 MNS 2.0 的數(shù)據(jù)層。該階段無(wú)法進(jìn)行平滑的回滾,是項(xiàng)目長(zhǎng)期驗(yàn)證后最終的遷移狀態(tài)。
上述可以總結(jié)為 :聚焦單個(gè)服務(wù),階段性遷移服務(wù)發(fā)現(xiàn)流量,從而達(dá)到類(lèi)似系統(tǒng)新功能發(fā)布時(shí)“灰度上線”的能力。當(dāng)然,這個(gè)策略還涉及一些細(xì)節(jié)在其中,比如,分開(kāi)存儲(chǔ)在雙寫(xiě)時(shí)需要重點(diǎn)去保證異常情況下的最終一致性等等,鑒于篇幅原因,這里就不詳細(xì)展開(kāi)討論了,而且業(yè)界針對(duì)這種情況都有一些成熟的做法。
另外,我們通過(guò)優(yōu)化命名服務(wù)發(fā)布系統(tǒng)的發(fā)版形式,實(shí)現(xiàn)自動(dòng)化的流量灰度策略,降低了人力成本,同時(shí)構(gòu)建了自動(dòng)化的遷移工具、巡檢工具,高效地進(jìn)行自動(dòng)化的數(shù)據(jù)遷移工作,能夠快速巡檢遷移后的鏈路風(fēng)險(xiǎn),保障新 MNS 2.0 的穩(wěn)定上線。
2.5 演進(jìn)總結(jié)
在美團(tuán)命名服務(wù)這樣的大型分布式系統(tǒng)優(yōu)化過(guò)程中,具體到架構(gòu)和功能設(shè)計(jì)層面,我們也做了不少的權(quán)衡和取舍,前面我們也提到,放棄了增量式的精準(zhǔn)變動(dòng)信息推送方式。在考慮性能的前提下,也沒(méi)有使用數(shù)據(jù)多維度營(yíng)運(yùn)能力更好的 MySQL 作為主要存取介質(zhì)等等。取舍的核心原則是: 改造目標(biāo)時(shí)強(qiáng)調(diào)業(yè)務(wù)收益,落地過(guò)程中減少業(yè)務(wù)感知 。
目前,MNS 2.0 主要成果如下:
- 重構(gòu)了 5 個(gè)已有的核心組件,研發(fā)了 2 個(gè)全新的系統(tǒng),完成公司 PaaS 層數(shù)十個(gè)服務(wù)的功能的適配改造,目前已成功遷移全公司 80% 以上的服務(wù),且在遷移過(guò)程中無(wú)重大事故。
- RTO 從數(shù)小時(shí)降到分鐘級(jí),RPO 為 0;全鏈路推送耗時(shí) TP999 從 90s 降到了 10s,推送成功率從 96% 提升到 99% 以上,基本完成了百萬(wàn)級(jí)別服務(wù)節(jié)點(diǎn)治理能力的建設(shè)。
- 集群數(shù)據(jù)按照業(yè)務(wù)線等多維度進(jìn)行拆分,建立了基于分級(jí)染色的 SLA 指標(biāo)和定期巡檢機(jī)制,同時(shí)根據(jù)公司實(shí)際場(chǎng)景增加了眾多的服務(wù)風(fēng)控審計(jì)功能,保障了業(yè)務(wù)安全。
- 云原生方面,支持了 Service Mesh,注冊(cè)發(fā)現(xiàn)流程融入了 Mesh 底層基礎(chǔ)設(shè)施。
四、命名服務(wù)對(duì)業(yè)務(wù)的賦能
命名服務(wù)本身作為基礎(chǔ)的技術(shù)中臺(tái)設(shè)施,在堅(jiān)持“以客戶為中心”,升級(jí)自身架構(gòu)的同時(shí),也從如下幾個(gè)方面對(duì)美團(tuán)的多個(gè)業(yè)務(wù)進(jìn)行賦能。
4.1 單元化 & 泳道
單元化(SET 化)是業(yè)界比較流行的容災(zāi)擴(kuò)展方案,關(guān)于美團(tuán)單元化的詳細(xì)內(nèi)容,可參考 OCTO 團(tuán)隊(duì)在本次 ArchSummit 中的另一個(gè)專(zhuān)題分享《SET 化技術(shù)與美團(tuán)點(diǎn)評(píng)實(shí)踐解密》。這里主要是從命名服務(wù)對(duì)單元化支撐的角度去解答這個(gè)問(wèn)題。
圖 13 命名服務(wù)對(duì)單元化的支持
如上圖所示,業(yè)務(wù)多種來(lái)源的外網(wǎng)流量在通過(guò)網(wǎng)關(guān)進(jìn)入內(nèi)網(wǎng)后,會(huì)借助命名服務(wù)提供的能力(SDK/Agent),并按照業(yè)務(wù)自定義的核心數(shù)據(jù)維度和機(jī)器屬性,給流量打上單元化標(biāo)簽,然后路由到標(biāo)簽匹配的下一跳,從而實(shí)現(xiàn)了單元間流量隔離。一個(gè)單元內(nèi)部,從服務(wù)節(jié)點(diǎn)到各種存儲(chǔ)組件,都依賴于命名服務(wù)提供的單元識(shí)別和路由能力來(lái)完成隔離,所以命名服務(wù)在單元化中主要起底層支撐的作用。
目前單元化在美團(tuán)的重點(diǎn)業(yè)務(wù),比如外賣(mài)、配送已經(jīng)建設(shè)的比較完備,通過(guò)一定的單元冗余度,能在一個(gè)單元出現(xiàn)問(wèn)題時(shí),切換到另一個(gè)可用的鏡像單元,顯著提高了業(yè)務(wù)整體可用性。
接下來(lái),我們?cè)賮?lái)看一下泳道場(chǎng)景。目前泳道在美團(tuán)這邊主要用于業(yè)務(wù)做完代碼 UT 之后的線下集成測(cè)試階段,同時(shí)結(jié)合容器,實(shí)現(xiàn)一個(gè)即插即用的上下游調(diào)用環(huán)境去驗(yàn)證邏輯。命名服務(wù)在其中起到的作用與單元化類(lèi)似,根據(jù)泳道發(fā)布平臺(tái)對(duì)機(jī)器的配置,自動(dòng)編排上下游的調(diào)用關(guān)系。如下圖所示:
圖 14 泳道流量示意圖
當(dāng)下一跳存在泳道節(jié)點(diǎn)時(shí),測(cè)試流量進(jìn)入泳道。反之,測(cè)試流量回流到主干。每個(gè)節(jié)點(diǎn)重復(fù)上述過(guò)程。
4.2 平滑發(fā)布 & 彈性伸縮
命名服務(wù)另外一個(gè)重要場(chǎng)景是服務(wù)的平滑發(fā)布,我們與發(fā)布平臺(tái)配合,控制發(fā)布流量的自動(dòng)摘除與恢復(fù),實(shí)現(xiàn)服務(wù)發(fā)布操作的自動(dòng)化與透明化。具體流程如下圖所示:
圖 15 命名服務(wù)支持平滑發(fā)布
早期的發(fā)布流程,存在異常調(diào)用的風(fēng)險(xiǎn),上線過(guò)程中存在一段服務(wù)實(shí)例不可用的“時(shí)間窗口”,此時(shí)流量再進(jìn)入可能導(dǎo)致調(diào)用失敗,然后會(huì)報(bào)錯(cuò)。為保證發(fā)布的穩(wěn)定性,需要操作人員手動(dòng)進(jìn)行流量排空,流程上效率低、易出錯(cuò),浪費(fèi)業(yè)務(wù)團(tuán)隊(duì)的時(shí)間。針對(duì)這項(xiàng)業(yè)務(wù)痛點(diǎn),命名服務(wù)向發(fā)布系統(tǒng)提供針對(duì)服務(wù)實(shí)例的流量管控能力,實(shí)現(xiàn)進(jìn)程重啟前自動(dòng)摘除并清空來(lái)源請(qǐng)求,升級(jí)完畢后,提供自動(dòng)流量恢復(fù)的平滑發(fā)布功能。智能地解決發(fā)版過(guò)程中的異常調(diào)用問(wèn)題,提高公司的服務(wù)上線效率,降低了業(yè)務(wù)團(tuán)隊(duì)的運(yùn)維成本。
彈性伸縮是容器一個(gè)很大的賣(mài)點(diǎn)。但是在伸縮過(guò)程中有很多問(wèn)題需要考慮,比如擴(kuò)縮容策略,包括調(diào)用親和度配置,路由均衡等等。命名服務(wù)和容器化合作,提供業(yè)務(wù)的上下游調(diào)用關(guān)系、分組設(shè)置信息、容器下線流量無(wú)損摘除等服務(wù),同時(shí)保障伸縮服務(wù)注冊(cè)及時(shí)、高效。如下圖所示:
圖 16 命名服務(wù)支持彈性伸縮
4.3 服務(wù)數(shù)據(jù)
MNS 服務(wù)數(shù)據(jù)對(duì)業(yè)務(wù)的賦能主要分為兩個(gè)部分,一是將自身運(yùn)行狀態(tài)以業(yè)務(wù)可理解的 SLA 暴露出來(lái),方便業(yè)務(wù)評(píng)估命名服務(wù)健康狀況。對(duì)于命名服務(wù)來(lái)說(shuō),SLA 指標(biāo)主要有 推送成功率和 推送耗時(shí) 兩種(其實(shí),推送耗時(shí)也可以看做成功率的一個(gè)衡量維度,這里暫時(shí)不做太詳細(xì)的區(qū)分)。
MNS 1.0 精準(zhǔn)量化運(yùn)行狀況的困難在于,一方面 MNS 的發(fā)布 / 訂閱機(jī)制重度依賴 ZK,受限于 ZK 的自身實(shí)現(xiàn)和鏈路上眾多不同組件的異構(gòu)性,及時(shí)獲取完整鏈路的推送行為數(shù)據(jù)很困難。另一方面,由于節(jié)點(diǎn)數(shù)眾多,全量采集服務(wù)發(fā)現(xiàn)數(shù)據(jù),對(duì)公司的監(jiān)控上報(bào)系統(tǒng)以及采集之后的計(jì)算也是很大的負(fù)擔(dān)。
在 MNS 2.0 中,我們首先在架構(gòu)上顯著弱化了 ZK 的地位,它基本上只作為一致性通知組件。我們自研的 MNS-Control 可以充分 diy 埋點(diǎn)場(chǎng)景,保證了主要推送行為抓取的可控性。其次,我們采用了分級(jí)采樣計(jì)算,在全面梳理了公司現(xiàn)有的服務(wù)節(jié)點(diǎn)數(shù)比例后,將典型的服務(wù)列表數(shù)劃分為幾個(gè)檔次,比如 1000 個(gè)節(jié)點(diǎn)的服務(wù)為一檔,100 個(gè)又為一檔,并創(chuàng)建相應(yīng)的非業(yè)務(wù)哨兵服務(wù),然后在不同機(jī)房選取適量的采樣機(jī)器定期注冊(cè) + 拉取來(lái)評(píng)估整體的運(yùn)行情況。這樣既做到了上報(bào)量的精簡(jiǎn),又兼顧了上報(bào)數(shù)據(jù)的有效性。詳細(xì)操作流程,如下圖所示:
圖 17 MNS 2.0 SLA 采集
- 控制層周期性修改采樣服務(wù)中的服務(wù)數(shù)據(jù),觸發(fā)服務(wù)發(fā)現(xiàn)的數(shù)據(jù)推送流程。
- 參與指標(biāo)統(tǒng)計(jì)的機(jī)器節(jié)點(diǎn),本地代理進(jìn)程獲取到注冊(cè)信息推送后,上報(bào)送達(dá)時(shí)間到運(yùn)維平臺(tái)并由其寫(xiě)入存儲(chǔ)層。
- 控制層對(duì)數(shù)據(jù)庫(kù)中的數(shù)據(jù)進(jìn)行聚合計(jì)算,最后上報(bào)監(jiān)控系統(tǒng)展示指標(biāo)數(shù)據(jù)。此外,通過(guò)與監(jiān)控團(tuán)隊(duì)合作,解決全量部署的 Agent 埋點(diǎn)監(jiān)控問(wèn)題。
命名服務(wù)存儲(chǔ)的服務(wù)信息有很高的業(yè)務(wù)價(jià)值,從中可以知道服務(wù)的部署情況、發(fā)布頻次以及上下游拓?fù)湫畔⒌鹊?。所?ldquo;賦能”的第二個(gè)部分在于,借助這些信息,我們可以挖掘出業(yè)務(wù)服務(wù)部署運(yùn)維上不合理的地方或風(fēng)險(xiǎn)點(diǎn),不斷推動(dòng)優(yōu)化,從來(lái)避免一些不必要的損失。目前已經(jīng)在推動(dòng)的項(xiàng)目包括:
- 單進(jìn)程多端口改造 :業(yè)務(wù)使用這種方式去區(qū)分不同的調(diào)用端口,從而造成端口資源的浪費(fèi),而且調(diào)用下游還要感知部署信息,這種機(jī)器屬性粒度細(xì)節(jié)的暴露在云原生時(shí)代是不太恰當(dāng)?shù)摹N覀儏f(xié)助業(yè)務(wù)將調(diào)用行為改成單端口多接口的形式,在協(xié)議內(nèi)部去區(qū)分調(diào)用邏輯。
- 大服務(wù)列表的拆分 :隨著業(yè)務(wù)的發(fā)展,單個(gè)服務(wù)的節(jié)點(diǎn)數(shù)呈爆發(fā)式增長(zhǎng),甚至出現(xiàn)了一個(gè)服務(wù)有接近 7W 的節(jié)點(diǎn)數(shù)的情況,對(duì)發(fā)布、監(jiān)控、服務(wù)治理等底層設(shè)施產(chǎn)生很大的壓力。我們通過(guò)和業(yè)務(wù)的溝通,發(fā)現(xiàn)大列表產(chǎn)生的原因主要有兩點(diǎn):1. 單機(jī)性能不夠,只能以實(shí)例抗;2. 服務(wù)內(nèi)容不夠聚焦。換句話說(shuō),因?yàn)榉?wù)還不夠“微”,所以導(dǎo)致邏輯越來(lái)越龐大,有需求的調(diào)用方和自身實(shí)例相應(yīng)增加,代碼風(fēng)險(xiǎn)也在增大。因此,我們和業(yè)務(wù)一起梳理分析架構(gòu)和調(diào)用,將核心共用模塊與業(yè)務(wù)邏輯群分拆出來(lái),減少冗余調(diào)用,最終使一些大服務(wù)節(jié)點(diǎn)數(shù)量從數(shù)萬(wàn)降低到數(shù)千,實(shí)現(xiàn)了數(shù)量級(jí)的下降。
- 上下游均衡部署 :這個(gè)比較容易理解,結(jié)合調(diào)用端與服務(wù)端比例、服務(wù)方機(jī)器性能以及調(diào)用失敗率等信息,可以作為服務(wù)業(yè)務(wù)在各機(jī)房間均衡調(diào)整機(jī)器數(shù)量的參考。另一方面,我們也在減少基于就近調(diào)用策略的粒度,目前只保留了“同 IDC”和“同城”兩種,去掉了之前的“同中心策略”,減輕業(yè)務(wù)服務(wù)部署的心智負(fù)擔(dān)。后期,隨著機(jī)房數(shù)量的降低和同地域機(jī)房間延時(shí)的可控,同城路由可能是最終的方案。
在架構(gòu)上,MNS 2.0 依賴 DB 和其它一些數(shù)倉(cāng)介質(zhì),進(jìn)行多種維度的數(shù)據(jù)上卷和下鉆,并結(jié)合一些定制的風(fēng)險(xiǎn)策略邏輯去幫助業(yè)務(wù)發(fā)現(xiàn)和規(guī)避問(wèn)題,目前這個(gè)事情也在進(jìn)行中。
圖 18 MNS 2.0 數(shù)據(jù)賦能
五、未來(lái)展望
未來(lái),美團(tuán)命名服務(wù)主要會(huì)朝兩個(gè)方向發(fā)展:
- 進(jìn)一步收集、挖掘服務(wù)數(shù)據(jù)的價(jià)值,打造服務(wù)數(shù)據(jù)平臺(tái),賦能業(yè)務(wù)升級(jí)。從單純實(shí)現(xiàn)業(yè)務(wù)注冊(cè)發(fā)現(xiàn)路由等需求,到通過(guò)數(shù)據(jù)反向推動(dòng)業(yè)務(wù)架構(gòu)流程改造升級(jí),這也是美團(tuán)核心價(jià)值觀“以客戶為中心”的一種體現(xiàn)。
- 深度結(jié)合 Service Mesh 等云原生基礎(chǔ)設(shè)施的演進(jìn)。云原生理念及相關(guān)設(shè)施架構(gòu)的快速發(fā)展,必然會(huì)造成傳統(tǒng)服務(wù)治理組件架構(gòu)上流程的變動(dòng),深度擁抱云原生,并享受基礎(chǔ)功能下沉帶來(lái)的“紅利”,是命名服務(wù)一個(gè)比較確定的方向。