【轉】手游頁游和端游的服務端的架構與區別

GameRes游資網發布, 文 /韋易笑

手游頁游和端游的服務端本質上沒區別,區別的是游戲類型。

類型1:卡牌、跑酷等弱交互服務端

卡牌跑酷類因為交互弱,玩家和玩家之間不需要實時面對面PK,打一下對方的離線數據,計算下排行榜,買賣下道具即可,所以實現往往使用簡單的 HTTP服務器:

登錄時可以使用非對稱加密(RSA, DH),服務器根據客戶端uid,當前時間戳還有服務端私鑰,計算哈希得到的加密 key 并發送給客戶端。之后雙方都用 HTTP通信,并用那個key進行RC4加密。客戶端收到key和時間戳后保存在內存,用于之后通信,服務端不需要保存 key,因為每次都可以根據客戶端傳上來的 uid 和 時間戳 以及服務端自己的私鑰計算得到。用模仿 TLS的行為,來保證多次 HTTP請求間的客戶端身份,并通過時間戳保證同一人兩次登錄密鑰不同。

每局開始時,訪問一下,請求一下關卡數據,玩完了又提交一下,驗算一下是否合法,獲得什么獎勵,數據庫用單臺 MySQL或者 MongoDB即可,后端的 Redis做緩存(可選)。如果要實現通知,那么讓客戶端定時15秒輪詢一下服務器,如果有消息就取下來,如果沒消息可以逐步放長輪詢時間,比如30秒;如果有消息,就縮短輪詢時間到10秒,5秒,即便兩人聊天,延遲也能自適應。

此類服務器用來實現一款三國類策略或者卡牌及酷跑的游戲已經綽綽有余,這類游戲因為邏輯簡單,玩家之間交互不強,使用 HTTP來開發的話,開發速度快,調試只需要一個瀏覽器就可以把邏輯調試清楚了。

類型2:第一代游戲服務器 1978

1978年,英國著名的財經學校University of Essex的學生 Roy Trubshaw編寫了世界上第一個MUD程序《MUD1》,在University of Essex于1980年接入 ARPANET之后加入了不少外部的玩家,甚至包括國外的玩家。《MUD1》程序的源代碼在 ARPANET共享之后出現了眾多的改編版本,至此MUD才在全世界廣泛流行起來。不斷完善的 MUD1的基礎上產生了開源的 MudOS(1991),成為眾多網游的鼻祖:

MUDOS采用 C語言開發,因為玩家和玩家之間有比較強的交互(聊天,交易,PK),MUDOS使用單線程無阻塞套接字來服務所有玩家,所有玩家的請求都發到同一個線程去處理,主線程每隔1秒鐘更新一次所有對象(網絡收發,更新對象狀態機,處理超時,刷新地圖,刷新NPC)。

游戲世界采用房間的形式組織起來,每個房間有東南西北四個方向可以移動到下一個房間,由于歐美最早的網游都是地牢迷宮形式的,因此場景的基本單位被成為 “房間”。MUDOS使用一門稱為LPC的腳本語言來描述整個世界(包括房間拓撲,配置,NPC,以及各種劇情)。游戲里面的高級玩家(巫師),可以不斷的通過修改腳本來為游戲添加房間以及增加劇情。早年 MUD1上線時只有17個房間,Roy Trubshaw畢業以后交給他的師弟 Richard Battle,在 Richard Battle手上,不斷的添加各種玩法到一百多個房間,終于讓 MUD發揚光大。

用戶使用 Telnet之類的客戶端用 Tcp協議連接到 MUDOS上,使用純文字進行游戲,每條指令用回車進行分割。比如 1995年國內第一款 MUD游戲《俠客行》,你敲入:"go east",游戲就會提示你:“后花園 - 這里是歸云莊的后花園,種滿了花草,幾個莊丁正在澆花。此地乃是含羞草生長之地。這里唯一的出口是 north。這里有:花待 阿牧(A mu),還有二位莊丁(Zhuang Ding)”,然后你繼續用文字操作,查看阿牧的信息:“look a mu”,系統提示:“花待 阿牧(A mu)他是陸乘風的弟子,受命在此看管含羞草。他看起來三十多歲,生得眉清目秀,端正大方,一表人才。他的武藝看上去【不是很高】,出手似乎【極輕】”。然后你可以選擇擊敗他獲得含羞草,但是你吃了含羞草卻又可能會中毒死亡。在早期網上資源貧乏的時候,這樣的游戲有很強的代入感。

用戶數據保存在文件中,每個用戶登錄時,從文本文件里把用戶的數據全部加載進來,操作全部在內存里面進行,無需馬上刷回磁盤。用戶退出了,或者每隔5分鐘檢查到數據改動了,都會保存會磁盤。這樣的系統在當時每臺服務器承載個4000人同時游戲,不是特別大的問題。從1991年的 MUDOS發布后,全球各地都在為他改進,擴充,退出新版本,隨著 Windows圖形機能的增強。1997游戲《UO》在 MUDOS的基礎上為角色增加的x,y坐標,為每個房間增加了地圖,并且為每個角色增加了動畫,形成了第一代的圖形網絡游戲。

因為游戲內容基本可以通過 LPC腳本進行定制,所以MUDOS也成為名副其實的第一款服務端引擎,引擎一次性開發出來,然后制作不同游戲內容。后續國內的《萬王之王》等游戲,很多都是跟《UO》一樣,直接在 MUDOS上進行二次開發,加入房間的地圖還有角色的坐標等要素,該架構一直為國內的第一代 MMORPG提供了穩固的支持,直到 2003年,還有游戲基于 MUDOS開發。

雖然后面圖形化增加了很多東西,但是這些MMORPG后端的本質還是 MUDOS。隨著游戲內容的越來越復雜,架構變得越來越吃不消了,各種負載問題慢慢浮上水面,于是有了我們的第二代游戲服務器。

類型3:第二代游戲服務器 2003

2000年后,網游已經脫離最初的文字MUD,進入全面圖形化年代。最先承受不住的其實是很多小文件,用戶上下線,頻繁的讀取寫入用戶數據,導致負載越來越大。隨著在線人數的增加和游戲數據的增加,服務器變得不抗重負。同時早期 EXT磁盤分區比較脆弱,稍微停電,容易發生大面積數據丟失。因此第一步就是拆分文件存儲到數據庫去。

此時游戲服務端已經脫離陳舊的 MUDOS體系,各個公司在參考 MUDOS結構的情況下,開始自己用 C在重新開發自己的游戲服務端。并且腳本也拋棄了 LPC,采用擴展性更好的 Python或者 Lua來代替。由于主邏輯使用單線程模型,隨著游戲內容的增加,傳統單服務器的結構進一步成為瓶頸。于是有人開始拆分游戲世界,變為下面的模型:

游戲服務器壓力拆分后得意緩解,但是兩臺游戲服務器同時訪問數據庫,大量重復訪問,大量數據交換,使得數據庫成為下一個瓶頸。于是形成了數據庫前端代理(DB Proxy),游戲服務器不直接訪問數據庫而是訪問代理,再有代理訪問數據庫,同時提供內存級別的cache。早年 MySQL4之前沒有提供存儲過程,這個前端代理一般和 MySQL跑在同一臺上,它轉化游戲服務器發過來的高級數據操作指令,拆分成具體的數據庫操作,一定程度上代替了存儲過程:

但是這樣的結構并沒有持續太長時間,因為玩家切換場景經常要切換連接,中間的狀態容易錯亂。而且游戲服務器多了以后,相互之間數據交互又會變得比較麻煩,于是人們拆分了網絡功能,獨立出一個網關服務 Gate(有的地方叫 Session,有的地方叫 LinkSvr之類的,名字不同而已):

把網絡功能單獨提取出來,讓用戶統一去連接一個網關服務器,再有網關服務器轉發數據到后端游戲服務器。而游戲服務器之間數據交換也統一連接到網管進行交換。這樣類型的服務器基本能穩定的為玩家提供游戲服務,一臺網關服務1-2萬人,后面的游戲服務器每臺服務5k-1w,依游戲類型和復雜度不同而已,圖中隱藏了很多不重要的服務器,如登錄和管理。這是目前應用最廣的一個模型,到今天任然很多新項目會才用這樣的結構來搭建。

人都是有慣性的,按照先前的經驗,似乎把 MUDOS拆分的越開性能越好。于是大家繼續想,網關可以拆分呀,基礎服務如聊天交易,可以拆分呀,還可以提供web接口,數據庫可以拆分呀,于是有了下面的模型:

這樣的模型好用么?確實有成功游戲使用類似這樣的架構,并且發揮了它的性能優勢,比如一些大型 MMORPG。但是有兩個挑戰:每增加一級服務器,狀態機復雜度可能會翻倍,導致研發和找bug的成本上升;并且對開發組挑戰比較大,一旦項目時間吃緊,開發人員經驗不足,很容易弄掛。

比如我見過某上海一線游戲公司的一個 RPG上來就要上這樣的架構,我看了下他們團隊成員的經驗,問了下他們的上線日期,勸他們用前面稍微簡單一點的模型。人家自信得很,認為有成功項目是這么做的,他們也要這么做,自己很想實現一套。于是他們義無反顧的開始編碼,項目做了一年多,然后,就沒有然后了。

現今在游戲成功率不高的情況下,一開始上一套比較復雜的架構需要考慮投資回報率,比如你的游戲上線半年內 PCU會去到多少?如果一個 APRG游戲,每組服務器5千人都到不了的話,那么選擇一套更為貼近實際情況的結構更為經濟。即使后面你的項目真的超過5千人朝著1萬人目標奔的話,相信那個時候你的項目已經掙大錢了 ,你數著錢加著班去逐步迭代,一次次拆分它,相信心里也是樂開花的。

上面這些類型基本都是從拆分 MUDOS開始,將 MUDOS中的各個部件從單機一步步拆成分布式。雖然今天任然很多新項目在用上面某一種類似的結構,或者自己又做了其他熱點模塊的拆分。因為他們本質上都是對 MUDOS的分解,故將他們歸納為第二代游戲服務器。

類型4:第三代游戲服務器 2007

從魔獸世界開始無縫世界地圖已經深入人心,比較以往游戲玩家走個幾步還需要切換場景,每次切換就要等待 LOADING個幾十秒是一件十分破壞游戲體驗的事情。于是對于 2005年以后的大型 MMORPG來說,無縫地圖已成為一個標準配置。比較以往按照地圖來切割游戲而言,無縫世界并不存在一塊地圖上面的人有且只由一臺服務器處理了:

每臺 Node服務器用來管理一塊地圖區域,由 NodeMaster(NM)來為他們提供總體管理。更高層次的 World則提供大陸級別的管理服務。這里省略若干細節服務器,比如傳統數據庫前端,登錄服務器,日志和監控等,統統用 ADMIN概括。在這樣的結構下,玩家從一塊區域走向另外一塊區域需要簡單處理一下:

玩家1完全由節點A控制,玩家3完全由節點B控制。而處在兩個節點邊緣的2號玩家,則同時由A和B提供服務。玩家2從A移動到B的過程中,會同時向A請求左邊的情況,并向B請求右邊的情況。但是此時玩家2還是屬于A管理。直到玩家2徹底離開AB邊界很遠,才徹底交由B管理。按照這樣的邏輯將世界地圖分割為一塊一塊的區域,交由不同的 Node去管理。

對于一個 Node所負責的區域,地理上沒必要連接在一起,比如大陸的四周邊緣部分和高山部分的區塊人比較少,可以統一交給一個Node去管理,而這些區塊在地理上并沒有聯系在一起的必要性。一個 Node到底管理哪些區塊,可以根據游戲實時運行的負載情況,定時維護的時候進行更改 NodeMaster 上面的配置。

于是碰到第一個問題是很多 Node服務器需要和玩家進行通信,需要問管理服務器特定UID為多少的玩家到底在哪臺 Gate上,以前按場景切割的服務器這個問題不大,問了一次以后就可以緩存起來了,但是現在服務器種類增加不少,玩家又會飄來飄去,按UID查找玩家比較麻煩;另外一方面 GATE需要動態根據坐標計算和哪些 Node通信,導致邏輯越來越厚,于是把:“用戶對象”從負責連接管理的 GATE中切割出來勢在必行于是有了下面的模型:

網關服務器再次退回到精簡的網絡轉發功能,而用戶邏輯則由按照 UID劃分的 OBJ服務器來承擔,GATE是按照網絡接入時的負載來分布,而 OBJ則是按照資源的編號(UID)來分布,這樣和一個用戶通信直接根據 UID計算出 OBJ服務器編號發送數據即可。而新獨立出來的 OBJ則提供了更多高層次的服務:

對象移動:管理具體玩家在不同的 Node所管轄的區域之間的移動,并同需要的 Node進行溝通。

數據廣播:Node可以給每個用戶設置若干 TAG,然后通知 Object Master 按照TAG廣播。

對象消息:通用消息推送,給某個用戶發送數據,直接告訴 OBJ,不需要直接和 GATE打交道。

好友聊天:角色之間聊天直接走 OBJ/OBJ MASTER。

整個服務器主體分為三層以后,NODE專注場景,OBJ專注玩家對象,GATE專注網絡。這樣的模型在無縫場景服務器中得到廣泛的應用。但是隨著時間的推移,負載問題也越來越明顯,做個活動,遠來不活躍的區域變得十分活躍,靠每周維護來調整還是比較笨重的,于是有了動態負載均衡。

動態負載均衡有兩種方法,第一種是按照負載,由 Node Master 定時動態移動修改一下各個 Node的邊界,而不同的玩家對象按照先前的方法從一臺 Node上遷移到另外一臺 Node上:

圖11 動態負載均衡

這樣 Node Master定時查找地圖上的熱點區域,計算新的場景切割方式,然后告訴其他服務器開始調整,具體處理方式還是和上面對象跨越邊界移動的方法一樣。

但是上面這種方式實現相對復雜一些,于是人們設計出了更為簡單直接的一種新方法:

圖12 基于網格的動態負載均衡

還是將地圖按照標準尺寸均勻切割成靜態的網格,每個格子由一個具體的Node負責,但是根據負載情況,能夠實時的遷移到其他 Node上。在遷移分為三個階段:準備,切換,完成。三個狀態由Node Master負責維護。準備階段新的 Node開始同步老 Node上面該網格的數據,完成后告訴NM;NM確認OK后同時通知新舊 Node完成切換。完成切換后,如果 Obj服務器還在和老的 Node進行通信,老的 Node將會對它進行糾正,得到糾正的 OBJ將修正自己的狀態,和新的 Node進行通信。

很多無縫動態負載均衡的服務端宣稱自己支持無限的人數,但不意味著 MMORPG游戲的人數上限真的可以無限擴充,因為這樣的體系會受制于網絡帶寬和客戶端性能。帶寬決定了同一個區域最大廣播上限,而客戶端性能決定了同一個屏幕到底可以繪制多少個角色。

從無縫地圖引入了分布式對象模型開始,已經完全脫離 MUDOS體系,成為一種新的服務端模型。又由于動態負載均衡的引入,讓無縫服務器如虎添翼,容納著超過上一代游戲服務器數倍的人數上限,并提供了更好的游戲體驗,我們稱其為第三代游戲服務端架構。網游以大型多人角色扮演為開端,RPG網游在相當長的時間里一度占據90%以上,使得基于 MMORPG的服務端架構得到了蓬勃的發展,然而隨著玩家對RPG的疲憊,各種非MMORPG游戲如雨后春筍般的出現在人們眼前,受到市場的歡迎。

類型5:戰網游戲服務器

經典戰網服務端和 RPG游戲有兩個區別:RPG是分區分服的,北京區的用戶和廣州區的用戶老死不相往來。而戰網,雖然每局游戲一般都是 8人以內,但全國只有一套服務器,所有的玩家都可以在一起游戲,而玩家和玩家之使用 P2P的方式連接在一起,組成一局游戲:

玩家通過 Match Making 服務器使用:創建、加入、自動匹配、邀請 等方式組成一局游戲。服務器會選擇一個人做 Host,其他人 P2P連接到做主的玩家上來。STUN是幫助玩家之間建立 P2P的牽引服務器,而由于 P2P聯通情況大概只有 75%,實在聯不通的玩家會通過 Forward進行轉發。

大量的連接對戰,體育競技游戲采用類似的結構。P2P有網狀模型(所有玩家互相連接),和星狀模型(所有玩家連接一個主玩家)。復雜的游戲狀態在網狀模型下難以形成一致,因此星狀P2P模型經受住了歷史的考驗。除去游戲數據,支持語音的戰網系統也會將所有人的語音數據發送到做主的那個玩家機器上,通過混音去重再編碼的方式返回給所有用戶。

戰網類游戲,以競技、體育、動作等類型的游戲為主,較慢節奏的 RPG(包括ARPG)有本質上的區別,而激烈的游戲過程必然帶來到較 RPG復雜的多的同步策略,這樣的同步機制往往帶來的是很多游戲結果由客戶端直接計算得出,那在到處都是破解的今天,如何保證游戲結果的公正呢?

主要方法就是投票法,所有客戶端都會獨立計算,然后傳遞給服務器。如果結果相同就更新記錄,如果結果不一致,會采取類似投票的方式確定最終結果。同時記錄本劇游戲的所有輸入,在可能的情況下,找另外閑散的游戲客戶端驗算整局游戲是否為該結果。并且記錄經常有作弊嫌疑的用戶,供運營人員封號時參考。

類型7:休閑游戲服務器

休閑游戲同戰網服務器類似,都是全區架構,不同的是有房間服務器,還有具體的游戲服務器,游戲主體不再以玩家 P2P進行,而是連接到專門的游戲服務器處理:

和戰網一樣的全區架構,用戶數據不能象分區的 RPG那樣一次性load到內存,然后在內存里面直接修改。全區架構下,為了應對一個用戶同時玩幾個游戲,用戶數據需要區分基本數據和不同的游戲數據,而游戲數據又需要區分積分數據、和文檔數據。勝平負之類的積分可以直接提交增量修改,而更為普遍的文檔類數據則需要提供讀寫令牌,寫令牌只有一塊,讀令牌有很多塊。同帳號同一個游戲同時在兩臺電腦上玩時,最先開始的那個游戲獲得寫令牌,可以操作任意的用戶數據。而后開始的那個游戲除了可以提交勝平負積分的增量改變外,對用戶數據采用只讀的方式,保證游戲能運行下去,但是會提示用戶,游戲數據鎖定。

類型8:現代動作類網游

從早期的韓國動作游戲開始,傳統的戰網動作類游戲和 RPG游戲開始嘗試融合。單純的動作游戲玩家容易疲倦,留存也沒有 RPG那么高;而單純 RPG戰斗卻又慢節奏的乏味,無法滿足很多玩家激烈對抗的期望,于是二者開始融合成為新一代的:動作 + 城鎮 模式。玩家在城鎮中聚集,然后以開副本的方式幾個人出去以動作游戲的玩法來完成各種 RPG任務。本質就是一套 RPG服務端+副本服務端。由于每次副本時人物可以控制在8人以內,因此可以獲得更為實時的游戲體驗,讓玩家玩的更加爽快。

說了那么多的游戲服務器類型,其實也差不多了,剩下的類型大家拼湊一下其實也就是這個樣子而已。游戲服務端經歷了那么多結構上的變遷,內部開發模式是否依然不變?究竟是繼續延續傳統的開發方式?還是有了更多突破性的方法?經歷那么多次架構變遷,后面是否有共通的邏輯?未來的發展還會存在哪些困難?游戲服務端開發如何達到最終的彼岸?

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,501評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,673評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,610評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,939評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,668評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,004評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,001評論 3 449
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,173評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,705評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,426評論 3 359
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,656評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,139評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,833評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,247評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,580評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,371評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,621評論 2 380

推薦閱讀更多精彩內容