微服務在遊戲服務端技術上的實踐及思考

遊戲服務端架構演進方向

網絡遊戲目前主要分爲四類:個人計算機客戶端網絡遊戲(PC端遊)、個人計算機網頁遊戲(PC頁遊)、手機客戶端網絡遊戲(手機端遊)、手機HTML5網絡遊戲(手機頁遊)。現在的遊戲服務端框架大體都是從最早的PC端遊時代演化而來,從單機系統向分佈式系統演化,從單體架構向微服務架構演化,詳細資料可查閱本文所列參考資料,這裏不再贅述,比較有代表性的開源遊戲服務端框架有:SkyNetPomeloComblockEngine(KBEngine)

DevOps逆向架構設計

我相信我們團隊和其他大多數團隊在研發運維上的設計差異較大,大部分團隊都是先從研發角度考慮軟件系統的架構設計,其次再考慮怎樣自動化運維,最後再考慮如何向DevOps方向轉化,而我們團隊是逆向設計的,我們先思考如何做DevOps,再思考怎樣的架構設計能更有利於自動化運維,最後纔是考慮系統架構設計,其實就是以終爲始。能這樣做主要是基於以下幾點:我們團隊沒有端遊、頁遊的歷史包袱,直接進入手遊時代;我們團隊主要研發策略養成類遊戲,系統架構需求和端遊、頁遊時代的MMORPG、MOBA差異較大,我們針對性重新設計並積極思考如何利用雲計算時代的微服務、容器技術更好地解決研發運維問題。2016年我們先從運維開始調研了一些自動化運維工具如SaltStack、Ansible、騰訊藍鯨平臺,那時容器技術已經在一線大型互聯網公司普及使用,我們也嘗試調研了容器技術。

當時調研後覺得容器技術是與雲計算環境結合緊密的技術(那時還不知道雲原生)而且比較徹底的解決了環境依賴問題(基礎設施即代碼),判斷這一定是未來運維的趨勢,所以果斷確定了今後的運維方向一定是基於容器技術,有了容器技術才能更好地支持持續集成和持續交付。我們當時已經做了一定程度的服務拆分,便開始在一些輔助服務的生產環境嘗試使用容器熱更新發布版本,實驗結果證明確實很好用。使用容器也帶來一些問題:服務是無狀態或將狀態轉移到共享存儲比較適合容器,如果容器保留狀態對於分佈式系統來說會比較複雜;要滿足分佈式系統服務的滾動更新、藍綠髮布、灰度發佈等熱更新需求,就需要有完善的容器監控管理工具,這就是容器編排;如果只是使用容器部署單體應用相對簡單,如果要微服務化則還要配套服務監控、服務註冊與發現、服務治理、配置中心、日誌聚合等一系列工具。

不管怎樣要部署大規模分佈式系統僅使用單個容器是不解決問題的,一定是要使用容器編排的。2016年容器技術正是羣雄逐鹿的年代,各種容器技術團隊混戰,這對於大多數研發團隊技術選型來說難以抉擇。我們當時對運維的思考是底層基礎運維全部依賴於雲商,我們只專注於做自研服務的運維,基於這種思路很自然容器編排的底層運維也依賴於雲商,這樣可以隨時切換基礎設施而不過多地投入調研,雲商有什麼我們就用什麼,當時阿里雲只有Docker Swarm產品,於是我們就選了Docker Swarm。天下大勢合久必分、分久必合,2017年容器編排羣雄混戰的局面終於結束,Kubernetes一統天下,阿里雲也很及時地同時上線了Kubernetes容器服務產品,我們果斷開始將容器編排方案向Kubernetes遷移。從Doker Swarm到Kubernetes我們團隊都是使用阿里雲容器服務的第一批客戶,也是首個遊戲行業用戶,阿里雲還專門爲我們建立了容器技術服務羣,協助解決各種產品問題和線上問題,我估計我們公司也是國內最早一批在遊戲項目生產環境大規模使用容器編排的公司,我們以實踐證明了完全使用容器編排運維遊戲項目的可行性而且確實極大地提升了運維效率。

到這裏DevOps流程中運維環節基本定型,我們還要打通從開發到運維的自動化環節,也就是持續集成和持續交付。有了容器技術支撐,剩下的問題就比較好解決,我們使用GitLab搭建持續集成流水線(現在已經支持Kubernetes),但還有些自動化工作需要細化。這裏順便提下我們對運維的願景和理念:我們希望運維成員是SRE工程師而不是像傳統運維幹體力活,提供運維解決方案而不是按照固定流程或模式去操作,後端服務誰開發誰運維(參考AWS),最終目標是人管理代碼、代碼管理機器、人不管機器(陳皓),總之方向是智能化和自動化。這對運維人員的要求比較高,傳統的運維人員研發能力較弱,但是SRE工程師要求同時具有開發、運維、架構設計能力,對於中小型公司從市場上招聘當然是很難的,所以我們完全是自己培養也用這樣的目標激勵團隊成長。如果把運維的目標定地過低,那運維最終就是純體力活,這樣招人是容易,但想做DevOps是不可能的。

在我看來開發不懂運維或是運維不懂開發想做好DevOps都是件困難的事,因爲無法以終爲始,有了DevOps基礎才能考慮微服務架構。

微服務化

首先說明一下我們爲什麼要微服務化,微服務是一把雙刃劍,解決一些問題的同時產生了另一些問題,所以在架構設計上要權衡利弊。微服務的技術棧和工具鏈比較複雜,需要投入較多的人力和時間成本,對於創業初期的小團隊我認爲是不太適合使用的,但可以做一定程度的服務拆分。系統架構往往是跟着業務模式演進的,是一個動態的過程,所以時機很重要,過早使用複雜的技術方案會影響研發進度,過晚重構或改進技術方案也會影響研發進度,這就是人們常說的短期看高估技術的作用長期看低估技術的作用。當一個公司隨着業務發展到一定規模後,研發要下沉並演化出技術中臺,阿里集團就是沿着這種路徑發展的,從最早的原始系統發展到研發數據庫、操作系統、人工智能、服務器、芯片。當一個小微公司向中型公司快速發展的時候,爲了更好地使技術服務於業務發展,就需要一個技術中臺支撐,這時可以考慮是否微服務化。再看我們的業務場景,策略養成類手遊的特點是弱聯網、高併發、水平擴展、高可用、彈性伸縮、持續交付,符合微服務解決的問題。微服務還有個很大的優點就是獨立部署和維護,這樣後續的技術迭代不會受到編程語言或其它環境的影響,服務之間從物理上解耦合有效降低了重構一個服務的成本,我們團隊現在的方案是依賴數據庫實現數據強一致性的,肯定不是最佳實踐,還有優化空間。

接着需要解決微服務帶來的問題:首當其衝的是響應時長會增加,這點對於策略養成類手游來說影響不大,但也需要做些性能優化;需要有服務降級、過載保護等容錯機制,避免併發阻塞引起整個系統雪崩;分佈式節點增加故障排查複雜度,需要有一套服務監控和調用鏈追蹤體系,日誌聚合是必不可少的,我們對比了Logstash、Fluentd、Flume等日誌收集工具,發現阿里雲Logtail性能和吞吐非常突出,而且可以和阿里雲容器服務無縫對接,但只能使用阿里雲的日誌服務接收日誌,不想自己搭建日誌聚合環境的可以試試;大規模集羣管理需要有服務註冊發現、配置中心配合容器編排等工具做服務治理;最難處理的一個問題是分佈式系統的數據一致性問題,遊戲不像其它互聯網系統多數情況下最終一致性或弱一致性就能滿足需求,遊戲很多場景都需要數據強一致性,這也是爲什麼遊戲項目難以微服務化的原因。

微服務配合容器技術可以實現高可用、水平擴展、熱更新,這些特性與手遊這種快速開新區服(滾服)的情況非常匹配。傳統遊戲服務端框架一般用腳本語言實現熱更新,而微服務架構則是使用藍綠髮布、灰度發佈、滾動更新等模式使用容器鏡像實現。

數據一致性

數據一致性問題一直是分佈式系統的一個經典難題,CAP和BASE理論是分佈式系統數據一致性問題的理論基礎。很不幸的是遊戲業務場景大多數需要數據強一致性,或者說數據強一致性能獲得良好的用戶體驗。

遊戲戰鬥模式分爲兩大類:PVE模式和PVP模式。其中,PVE模式又分爲個人戰和團戰,PVP模式又分爲本服個人戰、跨服個人戰、本服團戰、跨服戰團戰。不同遊戲類型不同模式在數據處理上的要求差異較大:PVE團戰可以轉化爲一個線性一致性隊列問題,根據對性能的不同要求處理細節也會有些區別,若業務場景要求強一致性需要做一些性能優化,若最終一致性能滿足要求異步返回結果就可以;PVP個人戰或本服團戰一般用鎖來控制數據一致性,使用鎖的前提是不能在同一時刻產生訪問臨界資源的高併發請求,否則會導致系統過載或響應延時;PVP跨服團戰傳統方案中解決數據一致性需要把不同區服的數據拉到同一個內存中,這樣就把分佈式數據一致性問題轉化成單機數據一致性問題。

傳統單體架構的遊戲服務端用鎖和內存基本能解決數據一致性問題,一般這種模式請求不直接訪問數據庫而是訪問內存,再以批量同步的方式將數據持久化。對於微服務來說解決數據一致性問題複雜度較高,通常微服務需要無狀態或將狀態轉移到共享存儲(一般就是數據庫或緩存),每個服務都使用自己的數據庫持久化,而且容器的生命週期是動態的,也就是說內存並不是固定的,這種模式天然就難以在內存中實現數據強一致性。一種方案是使用分佈式事務機制依賴數據庫實現,這種方案比較複雜而且對性能有一定影響。我們目前是使用數據庫事務和鎖結合解決,這時如果要處理跨服戰可能需要將不同區服數據同步到一個數據庫處理,否則就要實現分佈式事務。還有一種思路就是基於容器特性實現一套遊戲分佈式內存數據管理中間件,這種模式就需要在容器中保存狀態,並且需要處理容器調度時的數據遷移問題,這又是一個複雜的問題。

綜上所述,對於微服務的遊戲數據一致性解決方案還在探索和優化中,這也是引入微服務和容器技術的代價。對於我們團隊綜合評估來說,基於微服務和容器技術的遊戲技術中臺對遊戲後端研發生態的演進提供了一個基礎支撐平臺,在此平臺上不斷衍生出新的服務和技術支持並逐漸實現研運自動化,這是我們想看到的。

參考資料

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章