search
尋找貓咪~QQ 地點 桃園市桃園區 Taoyuan , Taoyuan

網游的跨服架構應該如何設計?

作者|江貴龍編輯|Cloes本文從當前遊戲市場發展的背景出發,實現了一套用於跨服通信的高吞吐的RPC通信框架,先後體驗了被動拉取模式帶來的坑,以及主動推送模式帶來的便利。並且,對該架構設計在消息組播,通信量,消息序列化/反序列化等進行了多方面機制的分析及深度優化。

雖然遊戲市場競爭激烈,產品格局變動較大,但遊戲產業一直處於穩步增長階段,無論是在端游,頁游,手游還是已經初露端倪的HTML5遊戲。可以預見,遊戲類型中,MMOARPG遊戲仍然會是引領市場的主流趨勢,貢獻著大部分流水,市場上也仍然在不斷湧現精品。研發團隊對MMO遊戲的探索從來未間斷過,從付費模式的改變,到題材多元化,次時代的視覺效果,更成熟的玩法及數值體系,本文主要針對跨服玩法上的探索和實現做一些思考和分析。

根據2016年《遊戲產業報告》數據顯示,隨著遊戲人口紅利逐漸消失,獲取用戶的成本居高不下,幾年來至少翻了十倍以上,目前平均導量成本頁游為10~15元/人,手游在15~20元/人,其中IOS上成本30~50元/人,「洗」用戶模式的效果正在變得微弱,用戶流失嚴重。讓我們先來看看滾服玩法的局限性,滾服洗量模式下存在著如下的弊端:

在上述背景下,一款長留存,低流失的精品遊戲就成了平台方,渠道商,研發方追捧的目標,設想一下,如果讓所有伺服器玩家通過「跨域體系」實現自由暢通交互,在此基礎上,玩家可以體驗到前所未有的「國戰系統」——7×24小時晝夜不停服的國家戰爭,隨時開戰;突破單地圖承載容量極限的國戰對決,帶來真正萬人國戰的刺激體驗,形成全區玩家能夠互動的遊戲社交環境。依託平台運營來打造一款真正意義上擺脫傳統遊戲運營模式的全新產品,為平台吸納足夠的市場份額,大幅降低流失率。

我們的藍圖是開創「1=1000」 模式,讓所有玩家,身處一個伺服器卻如同同時存在於所有伺服器,這種打破伺服器屏障的設定,杜絕了遊戲出現「被迫滾服」現象出現,玩家不用再擔心鬼服人煙稀少,不用擔心交易所一無所有,所有的數據共享,讓玩家輕鬆Hold住全世界。

項目組當時面臨的現狀是遊戲各種檔期計劃、宣傳推廣安排都已經就緒,兩個月後該獨代項目要在騰訊平台按時上線,開發不能因引入跨服機制而導致所有完成度100%的功能都要去分別去增加跨服的支持,而技術人員在跨服功能開發這塊經驗的積累上也不充分。

技術小組分析了時下項目的現狀,跨服業務需求及現有的框架結構,明確了幾點原則:

  • 為了實現跨服,遊戲代碼從底層架構到上層業務邏輯的代碼改動成本盡量降低

  • 業務邏輯里盡量少關心或者不用關心是否在本服或者跨服,降低開發人員的跨服功能開發複雜度,提高開發的效率,縮短開發周期。那麼,我們需要解決哪些技術疑點呢?

客戶端直連還是伺服器轉發

方案A,直連。如果直連,那麼,跨服玩法時客戶端要維持兩個連接,在跨服里,要模擬玩家登陸,綁定session的過程,遊戲服和跨服兩邊要同時維護兩份玩家數據,如何做到數據的同步?跨服要暴露給玩家,需要有公網訪問IP和埠。對客戶端連接管理來說較複雜。

方案B,轉發。如果通過大區伺服器消息轉發,那麼,伺服器之間做RPC通信,連接管理,消息需額外做一步跳轉,性能能否滿足?跨不跨服,對於客戶端來說透明,跨服隱藏在大區之後,更加安全,不需再浪費公網IP和埠。

綜合考慮了下,採用了B方案。

1. RPC框架設計需求

那麼,我們需要先準備一套高性能輕量級的RPC框架。業界有很多典型的RPC框架,比如Motan、Thrift、gRPC、Hessian、Hprose、Wildfly、Dubbo、DubboX,為什麼我們還要重複造輪子呢?綜合考慮了下,框架要滿足以下幾點業務需求:

  • 該框架要簡單、易用、支持高併發的跨服請求;

  • 根據現有的遊戲伺服器框架,會有很多定製化的場景;

  • 通過NIO TCP長連接獲取服務,但無需跨語言的需求;

  • 支持同步請求,非同步請求,非同步回調CallBack;

  • 要有服務發現的功能,要有Failfast能力;

  • 具備負載均衡,分組等路由策略;

基於有以上的訴求,結合團隊以前的開發經驗,於是就決定自主研發。我們選用的技術棧有 Netty、Apache Commons Pool、Redis等。

框架分為服務提供方(RPC Server)、服務調用方(RPC Client)、註冊中心(Registry)三個角色,基於Redis為服務註冊中心,通過其Pub/Sub實現服務動態的註冊和發現。Server 端會在服務初始化時向Registry 註冊聲明所提供的服務;Client 向 Registry 訂閱到具體提供服務的 Server 列表,根據需要與相關的 Server 建立連接,進行 RPC 服務調用。同時,Client 通過 Registry 感知 Server 的狀態變更。三者的交互關係如圖:

通過Global server提供路由策略,負載均衡策略,分組策略。具備 Failfast 能力,保障RPC服務一定程度的高可用。

2. RPC請求的有序性

連接池在設計過程中,比較重要的是要考慮請求的順序性,也就是先請求的先完成。如果玩家的跨服請求通過不同的RPC連接併發執行,就有可能單個玩家請求因錯序而導致邏輯矛盾,比如玩家移動,見圖2:

玩家移動是很頻繁的,如果A請求讓玩家從位置1移動到位置2,B請求從位置2移動到位置3,有可能B請求先被跨服接收處理,這就會產生邏輯問題。

那麼,如何做到請求的有序性呢?其本質是讓同一份數據的訪問能串列化,方法就是讓同一個玩家的跨服請求通過同一條RPC連接執行,加上邏輯上的有效性驗證,如圖3所示:

3. 同步RPC實現細節

限於篇幅,這裡只講同步請求的RPC連接池實現。同步請求的時序圖如圖所示:

上圖為進入跨服戰場的一次同步請求,場景切換控制器StageControllAction發起進入跨服戰場的請求applyChangeByBattlefield,場景管理器StageControllManager首先要調用登錄跨服的RPC請求GameRpcClient.loginCrossServer(LoginCrossServerReq),跨服RPC請求的工作流是這樣的:

該請求第一步先從連接池裡獲取一個連接RpcClient rpcClient = rpcClientPool.getResource(roleId),然後發起一個同步請求RpcClient.sendWithReturn,等待直到結果返回,然後把資源歸還連接池。

我們重點來看看sendWithReturn代碼實現:

測試場景為分別在連接數在1,8,併發數1,8,數據大小在22byte,94byte,2504byte情況下,做測試,消息同步傳輸,原樣返回,以下是針對同步請求壓力測試的結果(取均值):

伺服器之間主動推,還是被動拉取1. 被動拉取模式(Pull)

由於我們的遊戲伺服器和跨服伺服器代碼基本一致,所以只要能在跨服中獲得遊戲功能所要的數據,那麼,就能完成任何原有的功能,並且改造成本基本為零,我們選擇了被動拉取。

這裡要提出一個概念:數據源的相對性。

提供數據方,C向B請求一份數據,B是C的數據源,B向A請求一份數據,A是B的數據源。

一個玩家跨服過去后,往遊戲原服拉取數據的細節圖如圖:

玩家先跨服過去,loginCrossServer(LoginCrossServerReq),然後,在用到任意數據時(主角、技能、坐騎、裝備、寵物等),反向同步請求各個系統的數據。

我們的實現如下圖所示:

  • 玩家在遊戲本服,獲取Role數據,通過RoleRepository.cacheLoad(long roleId),先從Cache里讀取,沒有,則調用訪問器MySQLDataAccessor.load(EntityMappingem, Serializable roleId, K id)從資料庫讀取數據。

  • 玩家在跨服,獲取Role數據,通過RoleRepository.cacheLoad(long roleId),先從Cache里讀取,沒有,則調用訪問器NetworkDataAccessor.load(EntityMappingem, Serializable roleId, K id),通過RPC遠程同步調用讀取數據session.sendRPCWithReturn,該方法的實現可以參考上述的RpcClient.sendWithReturn,相類似。

關於被動拉取的優缺點介紹,在下文另有論述。總之,由於被動拉取的一些我們始料未及的缺陷存在,成為了我們伺服器端開發部分功能的噩夢,從選擇該模式時就埋下了一個天坑。

2. 主動推送模式(Push)

為了解決了上面碰到的一系列問題, 並且還能堅持最初的原則,我們做了如下幾點優化:

  • 如果玩家在本服,和調整前一樣的處理流程,如果玩家在跨服,客戶端請求的指令,發布的事件,非同步事件需要在場景Stage線程處理的,就轉發到跨服,需要在其他個人業務線程(bus),公共業務線程(public)處理的,仍舊在本服處理。

  • 場景業務線程不再允許有DB操作。

  • 內部指令的轉發、事件分發系統、非同步事件系統要在底層支持跨服。

  • 玩家在登錄本服時就會構PlayerTemplate, 場景用到的數據會實時更新,玩家去跨服,則會把場景中用到的數據PlayerTemplate主動推送給跨服。主動推送模式如下圖所示。

看下事件分發代碼的改造:

如下圖,舉個例子,在跨服怪物死亡后,會拋出 MonsterDeadEvent事件,在跨服進程直接處理場景的監聽對應的邏輯:

場景中道具掉落,屍體處理;其他的監聽邏輯拋回遊戲服處理,根據這事件,任務模塊處理完成任務,獲得獎勵;成就模塊處理完成成就,獲得獎勵;主角模塊獲得經驗,金幣等獎勵;活動模塊處理完成活動,獲得獎勵。

其他方面的優化1. 消息組播機制

消息組播的優化,在跨服,來自同一服的全部玩家廣播從分別單獨消息轉發,改成一個消息發回本服,然後再廣播給玩家(比如來自同一個服n個玩家,原本廣播一條消息,伺服器之間之間要處理n個RPC消息,現在只需要處理1個消息,降到了原先的1/n)。

2. 通信數據量

一個完整的PlayerTemplate模版數據由於包含了玩家在場景里用到的所有數據,比如角色、寵物、坐騎、裝備、神器、法寶、時裝、技能、翅膀等等, 數據量比較大,平均能達到5KB左右,需要在伺服器之間傳輸時做zlib壓縮,比如,做了壓縮后,11767 Byte的玩家數據能壓縮到2337Byte,壓縮率可達到19.86%。

3. 序列化/反序列化

改造前,所有的請求都需要先在本服做AMF3反序列化,如果請求是需要轉發到跨服的,再通過JSON序列化傳輸給跨服,在跨服通過JSON反序列化,最終該請求被處理。

但實際上,中間過程JSON序列化和反序列化似乎是沒有必要的,經過改造,對需要轉發給跨服的請求,在本服先不做AMF3反序列化,發送到跨服后再處理,這樣就少了一次JSON的序列化和反序列化,同時收益了另外的一個好處:降低了傳輸的位元組。

4. 內存佔用優化

Oracle JVM目前只能在JVM停止運行的時候才能做到釋放佔有內存,直到下次重啟,所以為了防止資源浪費,各種類型的跨服伺服器,遊戲伺服器都需要設置不同的啟動參數。啟動參數的設定根據我們自行設置的公式,如圖所示。

但內存佔用仍然會經常突破預警線90%,由於一旦系統分配內存發現不夠時,就會觸發自我保護機制,進行OOM killer,所以需要預留很大的內存給每個JVM進程,而且每次維護的時候去腳本修改內存也比較麻煩。

內存佔用狀況如上圖,伺服器更新維護后,內存佔用一路上揚,一直到最後維持在一定的值,不會回收,除非等下次維護或者系統觸發OOM killer。

基於阿里 JVM 1.8,只要開啟-XX:+DeallocateHeapPages,CMS能在不重啟應用的情況下把不使用的HEAP歸還給系統的物理內存,這樣,我們就不需要預留很多空間給JVM,再也不用擔心被誤殺了。

拿我們一款內測階段的遊戲舉例,使用了ALI JVM后, 64內存配置的機器最後開到了24個新區,相比起以前64G內存的機器,單台只能放9個獨立的遊戲區的狀況下,單區的成本將會節省62.5% 機器資源,非常可觀。完美的解決了內存經常吃緊的問題,並大幅節省了成本,這裡特別感謝阿里雲團隊和@坤谷提供黑科技,大家有需求的話,可以去申請成為種子用戶。

上圖就是使用了Ali JDK后的鋸齒形效果,每隔一定時間閑置內存會被系統回收,這在Oracle JVM是難以做到的。

5. 伺服器分組機制

不定向跨服是指任意遊戲區的玩家都有可能匹配到一起進行遊戲玩法的體驗,比如跨服戰場,比如跨服副本匹配,如圖所示(分別表示伺服器分組前和分組后)。

如何在遊戲正式大區中選擇幾個服做灰度服,又不影響不定向跨服體驗,以及如何解決新老服玩家戰力發展不在同一起跑線而導致的不平衡問題曾一度讓人糾結。

比如遊戲產品推出了大型資料片,想先做下灰度測試,讓1~4區的玩家先做下新功能的體驗,同時又能防止玩家穿了一件舊版本不存在的裝備而在跨服環境下報異常,根據運營需求通過分組,就很完美的解決了上述問題。

6. 戰區自動分配機制

定向跨服是指在一定時間內會固定參與跨服玩法的幾個國家,常用於戰區家之間對戰,如圖所示,需要運營在後台配置;當一段時間后,隨著玩家流失,又需要運營根據戰力進行戰區的調整,對運營人員的要求比較高。

調整后,每一種基於戰區的跨服類型都可以自定義調整時間間隔,到時間點全局伺服器(global server)系統自動根據全區的活躍戰力匹配進行調整,讓運營人員從繁雜的配置中解脫出來。

7. 跨服斷線重連機制

比如戰場系統或組隊副本,由於網路狀況而掉線,如果重新登錄后,沒法進入,將會嚴重影響戰場的戰況,順風局馬上就可能會變成逆風局,主力DPS掉線副本就有可能通不了,這個機制就彌補了這塊的缺陷。

支持的玩法

目前,我們已經能支持任意的遊戲區玩家可以到任意的跨服伺服器進行遊戲功能的體驗。比如已經實現的跨服組隊副本、跨服戰場、跨服國戰、跨服皇城爭奪、跨服資源戰、蟲群入侵戰、跨服押鏢、挖礦爭奪等。

也支持玩家在本服就可以進行跨服互動,比如和別的區的玩家聊天、加好友、送禮等無縫交互,及國家拍賣行,世界拍賣行的跨服貿易。甚至支持玩家穿越到另外的遊戲區做任意的遊戲體驗,比如一區的玩家聽說二區服在舉行搶親活動,你可以跑到2區去觀賞參與,也跑到任意的區的中央廣場去顯擺你的極品套裝。

跨服在線數據

跨服定向玩法有戰區國家玩法,蟲群入侵,跨服押鏢,挖礦爭奪, 跨服皇城爭奪,跨服國戰等,如下圖所示,我們可以看出這種玩法的規律:每次活動開啟,跨服就會迎來一波波玩家湧入,活動一結束,玩家就會離開,4個跨服進程支持了7600在線的玩家。

跨服非定向性玩法有跨服組隊副本,跨服戰場等,支持負載均衡,可以隨時動態增加跨服。這些玩法的規律是24小時隨時可以體驗進入,在線比較穩定,8個跨服進程支持了28000在線的玩家。

技術架構

下圖為跨服通信拓撲圖,屬於整體架構的核心部分,關於這一部分的說明見圖表:

關於整體架構的介紹,賣個關子,後續的文章會和大家分享。請大家關注聊聊架構公眾號。另外此套架構歷經了《大鬧天宮OL》、《諸神黃昏》、《暴風王座》、《驚天動地》、《三打白骨精》、《英雄領主》、《封神霸業》等先後近兩萬組伺服器運行的驗證和考驗。

作者介紹

江貴龍,遊戲行業從業8年,歷任多款遊戲項目伺服器主程,上海靈娛伺服器負責人。 關注遊戲伺服器架構及優化,監控預警,智能運維,數據統計分析等。

掃碼入群,與阿龍深度交流。

手機QQ春節紅包項目組的復盤總結

推薦一個對技術人員的成長很有幫助的線下會議,將於4月16~18日舉行的QCon全球軟體開發大會(北京站),目前已經邀請來自Google、Facebook、LinkedIn、Airbnb、百度、阿里巴巴、騰訊等公司的100多位一線技術專家,是難得的線下交流學習的機會。具體詳戳「 閱讀原文 」驚喜不停!



熱門推薦

本文由 yidianzixun 提供 原文連結

寵物協尋 相信 終究能找到回家的路
寫了7763篇文章,獲得2次喜歡
留言回覆
回覆
精彩推薦