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