前言
歡樂(lè)游戲工作室后臺(tái)是分布式微服務(wù)架構(gòu),目前穩(wěn)定承載著多款游戲,數(shù)千萬(wàn)DAU以及數(shù)百萬(wàn)級(jí)在線(xiàn)。原有云下架構(gòu)脫胎于QQGame后臺(tái),核心架構(gòu)已有10多年的歷史,其中使用了多套目的不同的自研開(kāi)發(fā)框架,自研基礎(chǔ)組件,并為適應(yīng)繁雜的業(yè)務(wù)場(chǎng)景,衍生出不同的服務(wù)模型,最終積累了數(shù)百個(gè)微服務(wù),整體簡(jiǎn)化架構(gòu)如下所示:
在這種大規(guī)模平臺(tái)化的后臺(tái)系統(tǒng)和復(fù)雜多樣的業(yè)務(wù)架構(gòu)下,還要持續(xù)創(chuàng)造更大的業(yè)務(wù)價(jià)值,這給團(tuán)隊(duì)帶來(lái)了較大的挑戰(zhàn)和壓力。
簡(jiǎn)單列舉幾個(gè)問(wèn)題:
·機(jī)器資源利用率極低,集群內(nèi)CPU峰值平均利用率不足20%;
·服務(wù)治理能力不足,由于存在多套研發(fā)框架且服務(wù)管理方式不同,導(dǎo)致整體業(yè)務(wù)的維護(hù)以及基礎(chǔ)服務(wù)治理能力的研發(fā)成本較高;
·服務(wù)部署十分繁瑣,自動(dòng)化不足,耗時(shí)耗力,且容易出外網(wǎng)問(wèn)題;
·大量的陳舊業(yè)務(wù)服務(wù)缺乏維護(hù),陳舊服務(wù)可視化能力不足,質(zhì)量不易保證;
·整體架構(gòu)較為復(fù)雜,新人上手成本較高,可維護(hù)性不足;
·每年機(jī)房裁撤都要耗費(fèi)較大人力成本;
在云原生時(shí)代,借著公司全面“擁抱云原生”的東風(fēng),我們深度結(jié)合K8s以及Istio能力,逐模塊拆分,細(xì)致梳理,經(jīng)歷過(guò)各類(lèi)有狀態(tài)、無(wú)狀態(tài)服務(wù)的上云,協(xié)議改造,框架改造適配,服務(wù)模型云原生化,數(shù)據(jù)遷移,完善云上周邊服務(wù)組件,建立云上服務(wù)DevOps流程等等眾多系統(tǒng)性工程改造。最終,在不停服、平滑兼容過(guò)渡的前提下,將整體架構(gòu)的服務(wù)云化以及網(wǎng)格化。
在整體架構(gòu)上云技術(shù)方案選型上,我們權(quán)衡了各類(lèi)方案的完備性、可擴(kuò)展性以及改造維護(hù)成本等因素,最終選擇使用Istio[1]服務(wù)網(wǎng)格作為整體上云的技術(shù)方案。
接下來(lái),我將按照原有架構(gòu)演進(jìn)的線(xiàn)路,簡(jiǎn)單介紹部分模塊的上云方案。
研發(fā)框架以及架構(gòu)升級(jí),實(shí)現(xiàn)低成本無(wú)感平滑演進(jìn)至服務(wù)網(wǎng)格
為了接入Istio以及服務(wù)能夠平滑過(guò)渡,在基礎(chǔ)框架和架構(gòu)上做了較多適配性調(diào)整,最終可以實(shí)現(xiàn):
1.存量業(yè)務(wù)代碼無(wú)需調(diào)整,重編即可支持gRPC協(xié)議;
2.網(wǎng)格服務(wù)之間調(diào)用,使用gRPC通信;
3.云下服務(wù)調(diào)用網(wǎng)格服務(wù),既可以使用私有協(xié)議也可以使用gRPC協(xié)議;
4.網(wǎng)格服務(wù)調(diào)用云下服務(wù),使用gRPC協(xié)議;
5.舊業(yè)務(wù)可平滑灰度遷移至網(wǎng)格內(nèi);
6.兼容Client側(cè)的私有協(xié)議請(qǐng)求;
接下來(lái),對(duì)其中部分內(nèi)容做簡(jiǎn)要說(shuō)明。
原有架構(gòu)引入gRPC
考慮到需要更全面應(yīng)用Istio的服務(wù)治理能力,我們?cè)谝延虚_(kāi)發(fā)框架中引入了gRPC協(xié)議棧。同時(shí)為了兼容原有的私有協(xié)議的通信能力,使用gRPC包裝私有協(xié)議,并在開(kāi)發(fā)框架層以及架構(gòu)層都做了兼容性處理。
開(kāi)發(fā)框架結(jié)構(gòu)示意圖如下所示:
使用MeshGate橋接網(wǎng)格以及云下服務(wù)
為了使得云上Istio中的服務(wù),能夠與云下服務(wù)互通,我們研發(fā)了MeshGate服務(wù)橋接云上網(wǎng)格以及云下服務(wù)。
MeshGate主要功能是實(shí)現(xiàn)服務(wù)在網(wǎng)格內(nèi)外的雙邊代理注冊(cè),并實(shí)現(xiàn)gRPC與私有協(xié)議之間的互轉(zhuǎn)適配,架構(gòu)如下圖所示:
架構(gòu)演變
基于業(yè)務(wù)重編支持gRPC能力,以及網(wǎng)格內(nèi)外服務(wù)兼容性的打通,我們就可以實(shí)現(xiàn)新舊業(yè)務(wù)無(wú)感平滑的遷移上云了。
當(dāng)然在遷移過(guò)程中,我們也并非一味無(wú)腦的容器化上云,會(huì)對(duì)各類(lèi)服務(wù)做針對(duì)性的云原生化處理以及服務(wù)質(zhì)量加固,并提高服務(wù)的可觀(guān)測(cè)性,最終提升服務(wù)的可維護(hù)性以及資源利用率。
服務(wù)上云之后,其資源配置粒度變?yōu)镻od級(jí)別,并支持自動(dòng)伸縮能力,因此無(wú)需為具體的服務(wù)預(yù)留過(guò)多資源,絕大部分服務(wù)都可以共用Node資源。進(jìn)而可以大幅提高機(jī)器資源的利用率,整體的資源使用降幅可達(dá)60-70%左右。
除了機(jī)器資源的減少好處之外,服務(wù)使用helm聲明式一鍵部署模式,從而K8s可以較好地維持服務(wù)的可用性,同時(shí)架構(gòu)也獲得了Istio強(qiáng)大的服務(wù)治理能力[2]。最終極好地提升了業(yè)務(wù)的DevOps效能。
整體架構(gòu)的演變?nèi)缦聢D所示:
但心細(xì)的同學(xué)可能會(huì)發(fā)現(xiàn),服務(wù)上了網(wǎng)格之后,業(yè)務(wù)和Client側(cè)的通信需要從自研接入集群Lotus轉(zhuǎn)發(fā)至MeshGate,并做多次的協(xié)議轉(zhuǎn)換以及轉(zhuǎn)發(fā),導(dǎo)致通信鏈路的性能開(kāi)銷(xiāo)以及時(shí)延加大。而對(duì)于游戲中時(shí)延敏感的業(yè)務(wù)場(chǎng)景,其中時(shí)延的損失,是難以接受的。因此我們迫切需要一個(gè)網(wǎng)格內(nèi)的網(wǎng)關(guān)接入服務(wù),接下來(lái)就介紹一下網(wǎng)關(guān)接入的改造方案。
網(wǎng)格內(nèi)私有協(xié)議的接入服務(wù)
原有云下的自研接入集群Lotus,是基于私有協(xié)議的TCP長(zhǎng)鏈接的Client側(cè)接入服務(wù),具備服務(wù)注冊(cè),大規(guī)模用戶(hù)鏈接管理,通信鑒權(quán),加解密,轉(zhuǎn)發(fā)等等能力。
除了前述服務(wù)遷移至網(wǎng)格后,導(dǎo)致通信效果損耗之外,還存在一些其他問(wèn)題:
1.Lotus集群的運(yùn)維十分繁瑣;因?yàn)闉榱朔乐褂脩?hù)游戲過(guò)程中出現(xiàn)鏈接的斷開(kāi)導(dǎo)致的不好體驗(yàn),Lotus進(jìn)程的停止,需要等待用戶(hù)側(cè)主動(dòng)斷開(kāi),而新鏈接則不會(huì)發(fā)送給待停的Lotus中,簡(jiǎn)而言之,Lotus的停止需要排空已有長(zhǎng)鏈接,這也導(dǎo)致Lotus的更新需要等待較長(zhǎng)的時(shí)間。我們有統(tǒng)計(jì)過(guò),每次全網(wǎng)更新發(fā)布Lotus版本需要持續(xù)數(shù)天的時(shí)間。而遇到問(wèn)題、裁撤或者新增節(jié)點(diǎn)時(shí),其變更需要人工調(diào)整全網(wǎng)配置策略,且需要執(zhí)行十多項(xiàng)步驟,整體效率較低。
2.Lotus集群的資源利用率低;由于Lotus是最基礎(chǔ)的服務(wù),且部署不方便,因此為了應(yīng)對(duì)業(yè)務(wù)流量的變化,就要預(yù)留出充足的機(jī)器資源。但這也導(dǎo)致了Lotus的資源利用率較低,日常CPU峰值資源利用率僅25%左右;
為此,我們基于CNCF旗下的開(kāi)源項(xiàng)目Envoy[3]的基礎(chǔ)之上,支持私有協(xié)議的轉(zhuǎn)發(fā),并對(duì)接Istio控制面,使之適配我們?cè)械臉I(yè)務(wù)模型,并實(shí)現(xiàn)私有通信鑒權(quán),加解密,客戶(hù)端鏈接管理等等能力,最終完成接入服上云的工作。
整體技術(shù)框架如下圖所示:
改造完畢之后,云上接入集群在各方面都獲得了較好的提升。
1.核心業(yè)務(wù)場(chǎng)景下的私有協(xié)議轉(zhuǎn)發(fā)性能以及延遲開(kāi)銷(xiāo)與云下環(huán)境接近;針對(duì)核心的業(yè)務(wù)場(chǎng)景,我們做過(guò)相應(yīng)的壓力測(cè)試,Envoy在支持私有協(xié)議之后,其接入轉(zhuǎn)發(fā)的性能開(kāi)銷(xiāo)以及時(shí)延與云下直連屬于同一個(gè)量級(jí)。其中測(cè)試時(shí)延,如下表所示:
2.天然支持Istio的服務(wù)治理能力,更貼近云原生Istio下的使用方式;
3.通過(guò)Helm部署以及定義Controller管理,實(shí)現(xiàn)一鍵服務(wù)上架以及滾動(dòng)更新;整個(gè)升級(jí)是自動(dòng)的,且過(guò)程中實(shí)現(xiàn)排空更新能力,并考慮會(huì)負(fù)載能力,排空效率更優(yōu)。
4.由于支持自動(dòng)伸縮能力,接入服務(wù)無(wú)需預(yù)留過(guò)多的資源,因此可以大幅降低資源開(kāi)銷(xiāo);全量云化后接入集群的CPU節(jié)省50%-60%,內(nèi)存節(jié)省了近70%左右。
架構(gòu)演變
有了云上接入集群,整體架構(gòu)演變?nèi)缟蠄D所示。接下來(lái)再以游戲業(yè)務(wù)中的GameSvr作為游戲強(qiáng)狀態(tài)服務(wù)的代表,簡(jiǎn)單介紹其上云方案。
GameSvr上云
歡樂(lè)工作室以往大都是單局房間類(lèi)的游戲(注:目前已經(jīng)遠(yuǎn)不止這些了,也有MMO,大世界,SLG等等各種游戲品類(lèi))。
云下GameSvr架構(gòu)如下圖所示:
但以上架構(gòu)在云下存在一些問(wèn)題:
1.運(yùn)維繁瑣;單臺(tái)GameSvr上下架需十余步人工操作,每年不停服機(jī)器裁撤需要耗費(fèi)數(shù)周的人力,且容易發(fā)生事故;
2.資源利用率低;同樣因?yàn)閿U(kuò)縮不易,就需預(yù)留足夠的資源,做冗余部署,導(dǎo)致高峰期CPU利用率僅20%左右;
3.整體的容災(zāi)能力弱,宕機(jī)后需人工介入處理;
4.對(duì)局調(diào)度不靈活,都是依靠人工配置靜態(tài)策略;
因此借助云原生的能力,我們打造了一套易伸縮、易維護(hù)和高可用的單局類(lèi)GameSvr架構(gòu)。如下圖所示:
在整個(gè)遷移上云的過(guò)程中,我們是不停服,不變更前端,用戶(hù)無(wú)感地平滑過(guò)渡至云上網(wǎng)格GameSvr集群。最終實(shí)現(xiàn)了:
1.資源利用率上獲得大幅提升;整體CPU以及內(nèi)存的使用都減少了近2/3。
2.運(yùn)維效率獲大幅提升;通過(guò)自定義CRD和Controller的管理,實(shí)現(xiàn)Helm一鍵部署整個(gè)集群,上下架十分便捷,僅一個(gè)業(yè)務(wù)項(xiàng)目組每個(gè)月因發(fā)布GameSvr都可以有效節(jié)省人力近10人天;
3.GameSvr可根據(jù)當(dāng)前集群的負(fù)載壓力變化以及歷史負(fù)載壓力的時(shí)間序列實(shí)現(xiàn)可靠自動(dòng)伸縮;
4.實(shí)現(xiàn)了靈活可靠的單局調(diào)度能力;通過(guò)簡(jiǎn)單的配置,即可實(shí)現(xiàn)單局根據(jù)不同的屬性,調(diào)度到不同的Set中。且在調(diào)度的過(guò)程中,也會(huì)考慮負(fù)載和服務(wù)質(zhì)量,最終實(shí)現(xiàn)整體調(diào)度的較優(yōu)選擇。
架構(gòu)演變
GameSvr上云之后,整體架構(gòu)變遷如上圖所示,接下來(lái)再看CGI是如何上云的。
數(shù)量龐大的CGI上云
我們?cè)笠?guī)模使用Apache下的CGI作為運(yùn)營(yíng)類(lèi)活動(dòng)開(kāi)發(fā)的框架。但原有CGI業(yè)務(wù)的一些現(xiàn)狀:
1.業(yè)務(wù)種類(lèi)較多,現(xiàn)網(wǎng)部署約350種CGI服務(wù),且流量巨大;
2.CGI同步阻塞的進(jìn)程模型,導(dǎo)致其單進(jìn)程的吞吐量極低;大部分CGI業(yè)務(wù)的QPS僅個(gè)位數(shù),且存在Apache的服務(wù)調(diào)度以及消息分發(fā)的性能開(kāi)銷(xiāo);
3.CGI之間的資源隔離性差;因?yàn)镃GI是同機(jī)多進(jìn)程部署,極易出現(xiàn)由于某個(gè)業(yè)務(wù)CGI突然資源開(kāi)銷(xiāo)暴增,影響其他業(yè)務(wù)CGI的情況;
面對(duì)數(shù)量龐大且性能低效的CGI的上云,則需要研發(fā)成本以及資源開(kāi)銷(xiāo)都低的上云方案。一開(kāi)始我們嘗試過(guò)將Apache以及CGI整體打包成一個(gè)鏡像簡(jiǎn)單容器化上云,但發(fā)現(xiàn)資源開(kāi)銷(xiāo)和部署模型都十分不理想,因此需要更優(yōu)雅的上云方案。
接著,我們對(duì)CGI的流量分布進(jìn)行分析,發(fā)現(xiàn)90%的業(yè)務(wù)流量主要集中在5%的CGI中,如下圖所示。
因此,我們針對(duì)不同流量的CGI,做了一些區(qū)分改造上云。
1.針對(duì)頭部流量CGI進(jìn)行協(xié)程異步化改造,剝離Apache,使框架性能獲數(shù)十倍提升。
·在框架層實(shí)現(xiàn)監(jiān)聽(tīng)http請(qǐng)求以及異步化:
-使用http-parser[4]改造,使得框架自身就支持http監(jiān)聽(tīng)以及處理;
-基于libco[5]改造,使框架底層支持協(xié)程,從而實(shí)現(xiàn)異步化;
·在業(yè)務(wù)層,也需要針對(duì)性做各類(lèi)適配性處理:
-針對(duì)全局變量,進(jìn)行私有化或者關(guān)聯(lián)至協(xié)程對(duì)象管理;
-后端網(wǎng)絡(luò)、io、配置加載以及內(nèi)存等資源做各類(lèi)復(fù)用化優(yōu)化,提升效率;
最終業(yè)務(wù)側(cè)做較小的調(diào)整,即可協(xié)程異步化改造完。但即使改造成本再低,已有的CGI數(shù)量還是太多了,全量異步化改造性?xún)r(jià)比十分低。
2.針對(duì)剩余長(zhǎng)尾流量CGI,與Apache一并打包,使用腳本一次性搬遷上云。為了提升可觀(guān)測(cè)性,還對(duì)這種單容器內(nèi),超多進(jìn)程的metrics采集export做了特殊處理。
最后在上云過(guò)程中,充分利用Apache的轉(zhuǎn)發(fā)機(jī)制,實(shí)現(xiàn)灰度可回滾上云。
上云后,CGI的整體資源利用率以及可維護(hù)性均獲大幅提升。全量云化之后CPU可節(jié)省近85%的核數(shù),內(nèi)存可節(jié)省70%左右。
架構(gòu)演變
搬遷完CGI之后,整體架構(gòu)如上圖所示。接下來(lái)介紹一下自研存儲(chǔ)CubeDB的改造方案。
自研存儲(chǔ)業(yè)務(wù)遷移
我們?cè)葡掠芯哂袛?shù)十T的自研存儲(chǔ)數(shù)據(jù),自建數(shù)百?gòu)圡ySQL表,整體的維護(hù)成本較高,且上云困難。因此我們的解決方案是“專(zhuān)業(yè)的事交給專(zhuān)業(yè)的人做”,將存儲(chǔ)遷移托管至TcaplusDB(騰訊IEG自研公共存儲(chǔ)服務(wù))。整體的遷移步驟簡(jiǎn)要描述如下:
1.研發(fā)了適配代理服務(wù),即上圖所示的Cube2TcaplusProxy,將CubeDB私有協(xié)議適配轉(zhuǎn)換至TcaplusDB,那么新業(yè)務(wù)的存儲(chǔ)就可以直接使用TcaplusDB了;
2.在CubeDB的備機(jī)同步業(yè)務(wù)的熱數(shù)據(jù),在開(kāi)啟同步之后,TcaplusDB就有業(yè)務(wù)的最新數(shù)據(jù);
3.將冷數(shù)據(jù)導(dǎo)入至TcaplusDB,如果TcaplusDB中有記錄數(shù)據(jù),說(shuō)明它是最新的,則不覆蓋;
4.全量比對(duì)MySQL與TcaplusDB的數(shù)據(jù),多次校驗(yàn)全量通過(guò)后則切換Proxy的路由;
最終通過(guò)這種方案,我們實(shí)現(xiàn)DB存儲(chǔ)的無(wú)損平滑遷移。
架構(gòu)演變
我們自研存儲(chǔ)服務(wù)改造完畢之后,絕大部分服務(wù)均可以上云了。同時(shí)我們還做了很多云上周邊能力的建設(shè)和應(yīng)用,例如云上統(tǒng)一配置中心,grafana as code,promethues,日志中心,染色調(diào)用鏈等等能力。
最終架構(gòu)演變?yōu)椋?/p>
多集群的部署模式
在云下,我們是一個(gè)全區(qū)全服的架構(gòu),所有的游戲業(yè)務(wù)都在一個(gè)集群之中。但由于我們組織架構(gòu)以及業(yè)務(wù)形態(tài)的原因,期望上云之后,不同的業(yè)務(wù)團(tuán)隊(duì)工作在不同的業(yè)務(wù)K8s集群,而對(duì)于大家共用的服務(wù),則放到公共集群下管理。因此在遷移上云的過(guò)程中,則還需要做更多的適配遷移工作。
在Istio層面,由于我們的Istio服務(wù)托管給TCM團(tuán)隊(duì)(騰訊云服務(wù)網(wǎng)格TCM[6]),在TCM同學(xué)的大力支持下,結(jié)合我們目前的組織架構(gòu)以及業(yè)務(wù)形態(tài),實(shí)現(xiàn)Istio多集群下控制面信息的互通,由此我們?cè)诙嗉褐g的互相調(diào)用,成本就很低了。如下是TCM相關(guān)的后臺(tái)架構(gòu):
總結(jié)
最終,我們?cè)趶?fù)雜的游戲業(yè)務(wù)架構(gòu)下,經(jīng)過(guò)細(xì)致分析和基于云原生技術(shù)的持續(xù)重構(gòu)演進(jìn),深度結(jié)合K8s以及Istio的能力,最終實(shí)現(xiàn)游戲業(yè)務(wù)場(chǎng)景下架構(gòu)平穩(wěn)平滑的高質(zhì)量上云以及網(wǎng)格化,擁有多框架多語(yǔ)言的微服務(wù)框架,自動(dòng)化,服務(wù)發(fā)現(xiàn),彈性伸縮,服務(wù)管控,流量調(diào)度治理,立體度量監(jiān)控等等能力,并沉淀游戲各類(lèi)業(yè)務(wù)場(chǎng)景上云經(jīng)驗(yàn)。對(duì)于業(yè)務(wù)模塊的可靠性、可觀(guān)測(cè)性、可維護(hù)性大幅提高,整體研運(yùn)效率提升十分明顯。
參考資料
[1]Istio:【https://istio.io/latest/about/service-mesh/】
[2]服務(wù)治理能力:【https://istio.io/latest/about/service-mesh/】
[3]Envoy:【https://www.envoyproxy.io/】
[4]http-parser:【https://github.com/nodejs/http-parser】
[5]libco:【https://github.com/Tencent/libco】
[6]騰訊云服務(wù)網(wǎng)格TCM:【https://cloud.tencent.com/product/tcm】
歡樂(lè)游戲工作室旗下?lián)碛袣g樂(lè)斗地主,歡樂(lè)麻將,歡樂(lè)升級(jí)等數(shù)款國(guó)民棋牌類(lèi)游戲,同時(shí)在研大世界,MMO,SLG等多種品類(lèi)游戲。