基于開源體系的云原生微服務(wù)治理實(shí)踐與探索
作者簡(jiǎn)介
CH3CHO,攜程高級(jí)研發(fā)經(jīng)理,負(fù)責(zé)微服務(wù)、網(wǎng)關(guān)等中間件產(chǎn)品的研發(fā)工作,關(guān)注云原生、微服務(wù)等技術(shù)領(lǐng)域。
一、攜程微服務(wù)產(chǎn)品的發(fā)展歷程
攜程微服務(wù)產(chǎn)品起步于2013年。最初,公司基于開源項(xiàng)目ServiceStack進(jìn)行二次開發(fā),推出.Net平臺(tái)下的微服務(wù)框架CServiceStack。
2014年,公司推出Java平臺(tái)下同CServiceStack完全互通的自研微服務(wù)框架Baiji和第一代服務(wù)注冊(cè)中心。該服務(wù)注冊(cè)中心后續(xù)經(jīng)歷多次重構(gòu),目前使用的已是第四代產(chǎn)品。
2017年,公司正式引進(jìn)開源產(chǎn)品Dubbo,推出整合攜程治理能力的CDubbo框架。該框架最初基于Dubbo 2.5.4版本進(jìn)行二次開發(fā),經(jīng)歷多次版本升級(jí)后,目前使用Dubbo 2.7.7版本。
2020年,公司正式開始探索落地Service Mesh項(xiàng)目。目前,相關(guān)產(chǎn)品已經(jīng)在生產(chǎn)環(huán)節(jié)正式落地,正在進(jìn)行接入推廣工作。
攜程微服務(wù)產(chǎn)品情況復(fù)雜,主要在于以下四點(diǎn)。
第一,線上同時(shí)運(yùn)行著三種微服務(wù)框架產(chǎn)品。
第二,同時(shí)采用HTTP和Dubbo兩種通信協(xié)議。
第三,采用完全自研的基礎(chǔ)設(shè)施,包括注冊(cè)中心和配置中心。
第四,現(xiàn)存8000多個(gè)線上服務(wù),實(shí)例數(shù)超過(guò)10萬(wàn)個(gè)。
隨著研發(fā)的深入,我們團(tuán)隊(duì)主要遇到了以下三點(diǎn)問(wèn)題。
第一,維護(hù)多個(gè)功能類似的中間件產(chǎn)品工作量較大,保證產(chǎn)品之間功能對(duì)齊需要花費(fèi)大量的精力。
第二,由于產(chǎn)品以SDK公共依賴包的形式集成在業(yè)務(wù)應(yīng)用內(nèi),進(jìn)行版本升級(jí)需要業(yè)務(wù)方配合,推動(dòng)升級(jí)比較困難,版本長(zhǎng)尾問(wèn)題嚴(yán)重。
第三,由于團(tuán)隊(duì)工作精力和技術(shù)棧的限制,只有少數(shù)幾個(gè)語(yǔ)言平臺(tái)上存在SDK支持,不利于小眾語(yǔ)言用戶使用微服務(wù)產(chǎn)品。?
二、攜程的云原生微服務(wù)架構(gòu)設(shè)計(jì)
由于線上集群已初具規(guī)模,如何平滑過(guò)渡和遷移框架成為關(guān)鍵問(wèn)題。徹底拋棄現(xiàn)有基礎(chǔ)設(shè)施,一步到位實(shí)現(xiàn)全面云原生,不僅實(shí)施難度較大,項(xiàng)目周期也比較長(zhǎng)。
因此,項(xiàng)目決定采用“小步快走”的方式。首先保證代碼完全向后兼容,其次保證整體架構(gòu)支持業(yè)務(wù)應(yīng)用遷移,提升接入容錯(cuò)率。
項(xiàng)目進(jìn)行架構(gòu)設(shè)計(jì)時(shí),遇到了三個(gè)關(guān)鍵的問(wèn)題。
數(shù)據(jù)權(quán)威問(wèn)題:常見的Service Mesh實(shí)踐以K8s為準(zhǔn)則,將所有的數(shù)據(jù)保存在K8s內(nèi),但平臺(tái)現(xiàn)有數(shù)據(jù)大部分保存在自研的注冊(cè)中心和配置中心內(nèi)。
有方案提出采用兩條推送路的方式,云內(nèi)數(shù)據(jù)保存在K8s內(nèi),云外數(shù)據(jù)保存在現(xiàn)有注冊(cè)中心里,通過(guò)外部工具或組件實(shí)現(xiàn)雙向同步。但雙向同步復(fù)雜度較高,既要保證數(shù)據(jù)的準(zhǔn)確性和實(shí)時(shí)性,也要保證同步不成環(huán)。
因此,出于架構(gòu)簡(jiǎn)便性考慮,項(xiàng)目最終選擇保持注冊(cè)中心數(shù)據(jù)權(quán)威地位不變,通過(guò)外部組件將數(shù)據(jù)寫入K8s。
邊界劃分問(wèn)題:目前的項(xiàng)目部署體系是一個(gè)Region內(nèi)包含多個(gè)Zone,一個(gè)Zone內(nèi)又包含多個(gè)K8s集群,集群之間網(wǎng)絡(luò)互通。但由于故障隔離的需要,數(shù)據(jù)最好保持在Zone內(nèi)收斂,使實(shí)例信息不需要進(jìn)行跨Zone同步。
Zone內(nèi)收斂存在的問(wèn)題是當(dāng)調(diào)用方發(fā)起跨Zone調(diào)用時(shí),需要經(jīng)過(guò)網(wǎng)關(guān)進(jìn)行中轉(zhuǎn)。這種調(diào)用方式和現(xiàn)有的調(diào)用鏈路存在差異,會(huì)提高計(jì)算復(fù)雜度。
因此,項(xiàng)目最終選擇保持現(xiàn)有工作模式不變,使得調(diào)用方能夠獲取Region內(nèi)所有的Zone服務(wù)實(shí)例,保持?jǐn)?shù)據(jù)在Region內(nèi)透明。
技術(shù)選型問(wèn)題:過(guò)去,項(xiàng)目研發(fā)產(chǎn)品大部分采用自研模式,通過(guò)整個(gè)團(tuán)隊(duì)成員協(xié)作完成開發(fā)工作,而依托開源社區(qū)能夠更容易地產(chǎn)出優(yōu)秀產(chǎn)品。
因此,項(xiàng)目最終選擇基于開源產(chǎn)品進(jìn)行二次開發(fā)。
目前所使用的Service Mesh架構(gòu)設(shè)計(jì),也被稱為“漸進(jìn)性”架構(gòu),主要有三個(gè)方面的特點(diǎn)。
開源方面:選擇Istio和Envoy作為Service Mesh的基礎(chǔ)設(shè)施。
實(shí)例和配置同步方面:由新開發(fā)的SOA Operator負(fù)責(zé)將存儲(chǔ)在注冊(cè)中心和配置中心中的數(shù)據(jù)寫入K8s。
同時(shí),該程序也會(huì)把K8s集群內(nèi)服務(wù)提供方的數(shù)據(jù)寫入注冊(cè)中心,使得K8s集群外用戶也能夠正常讀取服務(wù)數(shù)據(jù)。并且,該服務(wù)不需要SDK支持,由SOA Operator直接完成注冊(cè)和發(fā)現(xiàn),任何語(yǔ)言都可以方便地接入微服務(wù)產(chǎn)品體系。
使用方面:K8s集群外的應(yīng)用仍然使用過(guò)去的交互方式,通過(guò)SDK和注冊(cè)中心進(jìn)行通信。
K8s集群內(nèi)的應(yīng)用,如果使用SDK,檢測(cè)到Sidecar存在之后,SDK會(huì)自動(dòng)地關(guān)閉服務(wù)治理功能,使用特殊的host進(jìn)行請(qǐng)求。如果不存在SDK支持,接入Mesh可以直接使用HTTP Client,繼續(xù)使用特殊的host發(fā)起請(qǐng)求。
HTTP協(xié)議在Service Mesh架構(gòu)上運(yùn)行良好,但Dubbo協(xié)議在Sidecar網(wǎng)關(guān)上存在一些問(wèn)題。
其一,元數(shù)據(jù)的位置:HTTP協(xié)議中元數(shù)據(jù)位于報(bào)文最前端,而Dubbo協(xié)議中元數(shù)據(jù)位于報(bào)文末端,因此需要先解析報(bào)文才能定位到元數(shù)據(jù)位置。
其二,序列化問(wèn)題:解析報(bào)文需要對(duì)報(bào)文進(jìn)行反序列化處理,目前Envoy支持Dubbo默認(rèn)序列化協(xié)議。但這種方式會(huì)產(chǎn)生額外開銷,而且Dubbo服務(wù)使用的序列化器復(fù)雜,甚至還有一些團(tuán)隊(duì)為進(jìn)一步降低報(bào)文大小,使用了壓縮算法,網(wǎng)關(guān)解析難度大。
Dubbo 3推出了Triple,這是一種使用基于HTTP/2的gRPC并通過(guò)請(qǐng)求標(biāo)頭實(shí)現(xiàn)元數(shù)據(jù)信息傳遞的通信協(xié)議,也是Dubbo 3中推薦使用的服務(wù)通信協(xié)議。
Triple協(xié)議適用于Envoy框架,且能輕松接入Service Mesh。Dubbo版本升級(jí)也并不復(fù)雜。
由于gRPC的PB序列化格式,Triple協(xié)議無(wú)法直接使用。盡管Triple協(xié)議對(duì)PB兼容性較好,但PB要求先寫契約再生成代碼,而Dubbo要求先寫代碼,不存在契約,數(shù)據(jù)模型也是與PB對(duì)象完全不同的POJO格式。
為了連接POJO和PB對(duì)象,Triple協(xié)議設(shè)計(jì)了Wrapper。將原POJO對(duì)象序列化處理得到二級(jí)數(shù)據(jù)后,傳入到Wrapper用PB進(jìn)行序列化。
然而,這種方式不僅會(huì)導(dǎo)致內(nèi)存占用變大,而且會(huì)引發(fā)更多的GC。多次GC和重復(fù)序列化將會(huì)增大CPU負(fù)載。
為解決Triple協(xié)議帶來(lái)的問(wèn)題,項(xiàng)目給gRPC添加了自定義序列化器。這樣不僅可以實(shí)現(xiàn)流式的序列化,也可以為用戶提供和原生Dubbo一樣的使用體驗(yàn)。
其他語(yǔ)言想要調(diào)用這種gRPC服務(wù),只需要具備這種自定義序列化器即可,默認(rèn)的自定義序列化器JSON可以被大部分語(yǔ)言解析。
治理方面,Service Mesh使用Istio和Envoy作為基礎(chǔ)設(shè)施,通過(guò)Istio讀取K8s中CRD數(shù)據(jù),并生成配置推送給Envoy。
因此,保存在自研服務(wù)治理系統(tǒng)里內(nèi)的實(shí)例數(shù)據(jù)、配置數(shù)據(jù)必須全部轉(zhuǎn)化成CRD格式,同步到K8s以供Istio處理。
Operator作為翻譯機(jī)包含了大量模型轉(zhuǎn)換邏輯,能夠?qū)⑴渲媚P头g成CRD模型。針對(duì)一些復(fù)雜的功能,項(xiàng)目通過(guò)Envoyfilter或者Envoy的二次開發(fā),添加自定義的Envoyfilter進(jìn)行實(shí)現(xiàn)。
目前,所有的常用功能都已完成對(duì)齊,整體功能覆蓋率超90%。數(shù)千個(gè)線上應(yīng)用完成接入,進(jìn)入后續(xù)接入推廣工作。
三、云原生微服務(wù)產(chǎn)品的未來(lái)發(fā)展趨勢(shì)
Service Mesh提供的都是通用能力,如分組、路由、流量控制、負(fù)載均衡等。這些功能本身沒有語(yǔ)義,一線的業(yè)務(wù)研發(fā)和運(yùn)維人員理解起來(lái)存在一定困難。
而且,該產(chǎn)品功能與現(xiàn)存治理系統(tǒng)的功能存在差異。為了給一線人員提供更好的微服務(wù)治理體驗(yàn),需要將實(shí)際運(yùn)維需求和底層控制數(shù)據(jù)聯(lián)系起來(lái)。
目前,社區(qū)內(nèi)Dubbo Mesh的研發(fā)工作也在積極進(jìn)行,其做法跟攜程云原生微服務(wù)治理框架類似。通過(guò)單獨(dú)的控制面將配置數(shù)據(jù)寫到K8s里,將實(shí)例數(shù)據(jù)通過(guò)MCP進(jìn)行同步。
另外,新的開源產(chǎn)品OpenSergo也在研發(fā)中。據(jù)官方介紹,該項(xiàng)目力圖打造一套通用的面向云原生的微服務(wù)治理標(biāo)準(zhǔn),并且提供一系列的API和SDK實(shí)踐。
目前,多家大型互聯(lián)網(wǎng)企業(yè)和開源社區(qū)正在共同推進(jìn)該項(xiàng)目的進(jìn)行,希望能夠完成從服務(wù)治理到云原生基礎(chǔ)設(shè)施的全鏈路生態(tài)覆蓋。