遊戲服務器架構演進(完整版)

​這是王者榮耀技術分析系列第三篇,有興趣請持續關注個人blog和公衆號。node

一、像《王者榮耀》同樣紅過nginx

二、從《王者榮耀》來聊聊遊戲的幀同步web

三、遊戲服務器的架構演進數據庫

 

1、遊戲服務器特徵

遊戲服務器,是一個會長期運行程序,而且它還要服務於多個不定時,不定點的網絡請求。因此這類服務的特色是要特別關注穩定性和性能。這類程序若是須要多個協做來提升承載能力,則還要關注部署和擴容的便利性;同時,還須要考慮如何實現某種程度容災需求。因爲多進程協同工做,也帶來了開發的複雜度,這也是須要關注的問題。編程

功能約束,是架構設計決定性因素。基於遊戲業務的功能特徵,對服務器端系統來講,有如下幾個特殊的需求:後端

遊戲和玩家的數據存儲落地緩存

對玩家交互數據進行廣播和同步服務器

重要邏輯要在服務器上運算,作好驗證,防止外掛。網絡

針對以上的需求特徵,在服務器端,咱們每每會關注對電腦內存和CPU的使用,以求在特定業務代碼下,能儘可能知足高承載低響應延遲的需求。最基本的作法就是「空間換時間」,用各類緩存的方式來以求得CPU和內存空間上的平衡。另外還有一個約束:帶寬。網絡帶寬直接限制了服務器的處理能力,因此遊戲服務器架構也一定要考慮這個因素。多線程

 

2、遊戲服務器架構要素

    對於遊戲服務端架構,最重要的三個部分就是,如何使用CPU、內存、網卡的設計:

內存架構:主要決定服務器如何使用內存,以最大化利用服務器端內存來提升承載量,下降服務延遲。

邏輯架構:設計如何使用進程、線程、協程這些對於CPU調度的方案。選擇同步、異步等不一樣的編程模型,以提升服務器的穩定性和承載量。能夠分區分服,也能夠採用世界服的方式,將相同功能模塊劃分到不一樣的服務器來處理。

通訊模式:決定使用何種方式通信。基於遊戲類型不一樣採用不一樣的通訊模式,好比http,tcp,udp等。

 

3、服務器演化進程

一、卡牌等休閒遊戲弱交互遊戲

服務器基於遊戲類型不一樣,所採用的架構也有所不一樣,咱們先講一下簡單的模型,採用http通訊模式架構的服務器:

這種服務器架構和咱們經常使用的web服務器架構差很少,也是採用nginx負載集羣支持服務器的水平擴展,memcache作緩存。惟一不一樣的地點不一樣的在於通訊層須要對協議再加工和加密,通常每一個公司都有本身的一套基於http的協議層框架,不多采用開源框架。

 

二、長連接遊戲服務器

長鏈接遊戲和弱聯網遊戲不一樣的地方在於,長鏈接中,玩家是有狀態的,服務器能夠時時和client交互,數據的傳送,不像弱聯網通常每次都須要從新建立一個鏈接,消息傳送的頻率以及速度上都快於弱聯網遊戲。長連接網遊的架構通過幾代的迭代,類型也變得日益豐富,如下爲每一代服務器的特色以及架構模式。

 

1)、第一代網遊服務器(單線程無阻塞)

最先的遊戲服務器是1978年,英國著名的財經學校University of Essex的學生 Roy Trubshaw編寫了世界上第一個MUD程序,叫作《MUD1》。

MUD1 是一款純文字的世界,沒有任何圖片,可是不一樣計算機前的玩家能夠在遊戲裏共同冒險、交流。與以往具備網絡聯機功能的遊戲相比, MUD1是第一款真正意義上的實時多人交互的網絡遊戲,它最大的特點是可以保證整個虛擬世界和玩家角色的持續發展——不管是玩家退出後從新登陸仍是服務器重啓,遊戲中的場景、寶箱、怪物和謎題仍保持不變,玩家的角色也依然是上次的狀態。

MUD中文版

MUDOS使用單線程無阻塞套接字來服務全部玩家,全部玩家的請求都發到同一個線程去處理,主線程每隔1秒鐘更新一次全部對象(網絡收發,對象狀態,刷新地圖,刷新NPC)。用戶使用 Telnet之類的客戶端用 Tcp協議鏈接到 MUDOS上,使用純文字進行遊戲,每條指令用回車進行分割。這樣的系統在當時每臺服務器承載個4000人同時遊戲。從1991年的 MUDOS發佈後,全球各地都在爲他改進,擴充,推出新版本。

 

MUDOS中游戲內容經過 LPC腳本進行定製,邏輯處理採用單線程tick輪詢,這也是第一款服務端架構模型,後來被應用到不一樣遊戲上。後續不少遊戲都是跟《UO》同樣,直接在 MUDOS上進行二次開發,直到 現在,一些回合制遊戲,以及對運算量小的遊戲,依然採用這種服務器架構。

 

第一代服務器架構圖:

線程模型


2) 、第二代網遊服務器(分區分服)

2000年左右,隨着圖形界面的出現,遊戲更多的採用圖形界面與用戶交互。此時隨着在線人數的增長和遊戲數據的增長,服務器變得不抗重負。因而就有了分服模型。分服模型結構以下:


分服模型是遊戲服務器中最典型,也是歷久最悠久的模型。在早期服務器的承載量達到上限的時候,遊戲開發者就經過架設更多的服務器來解決。這樣提供了不少個遊戲的「平行世界」,讓遊戲中的人人之間的比較,產生了更多的空間。其特徵是遊戲服務器是一個個單獨的世界。每一個服務器的賬號是獨立的,每臺服務器用戶的狀態都是不同的,一個服就是一個世界,你們各不牽扯。

後來遊戲玩家呼籲要跨服打架,因而就出現了跨服戰,再加上隨着遊戲的運行,單個服務器的遊戲活躍玩家愈來愈少,因此後期就有了服務器的合併以及遷移,慢慢的以服務器的開放、合併造成了一套成熟的運營手段。目前多數遊戲還採用分服的結構來架設服務器,多數頁遊仍是採用這種模式。

線程調度

分服雖然能夠解決服務器擴展的瓶頸,但單臺服務器在之前單線程的方式來運行,沒辦法充分利用服務器資源,因而又演變出瞭如下2種線程模型。

異步-多線程,基於每一個場景(或者房間),分配一個線程。每一個場景的玩家同屬於一個線程。遊戲的場景是固定的,不會不少,如此線程的數量能夠保證不會不斷增大。每一個場景線程,一樣採用tick輪詢的方式,來定時更新該場景內的(對象狀態,刷新地圖,刷新NPC)數據狀態。玩家若是跨場景的話,就採用投遞和通知的方式,告知兩個場景線程,以此更新兩個場景的玩家數據。

 

多進程。因爲單進程架構下,總會存在承載量的極限,越是複雜的遊戲,其單進程承載量就越低,所以必定要突破進程的限制,才能支撐更復雜的遊戲。多進程系統的其餘一些好處:可以利用上多核CPU能力、更容易進行容災處理。

 

多進程系統比較經典的模型是「三層架構」,好比,基於以前的場景線程再作改進,把網絡部分和數據庫部分分離爲單獨的進程來處理,邏輯進程專心處理邏輯任務,不合IO打交道,網絡IO和磁盤IO分別交由網路進程和DB進程處理。

 

3)、第三代網遊服務器

以前的網遊服務器都是分區分服,玩家都被劃分在不一樣的服務器上,每臺服務器運行的邏輯相同,玩家不能在不一樣服務器之間交互。想要更多的玩家在同一世界,保持玩家的活躍度,因而就有了世界服模型了。世界服類型也有如下3種演化:

 

一類型(三層架構)

網關部分分離成單端的gate服務器,DB部分分離爲DB服務器,把網絡功能單獨提取出來,讓用戶統一去鏈接一個網關服務器,再有網關服務器轉發數據到後端遊戲服務器。而遊戲服務器之間數據交換也統一鏈接到網管進行交換。全部有DB交互的,都鏈接到DB服務器來代理處理。


二類型(cluster)

有了一類型的經驗,後續確定是拆分的越細,性能越好,就相似如今微服務,每一個相同的模塊分佈到一臺服務器處理,多組服務器集羣共同組成一個遊戲服務端。通常地,咱們能夠將一個組內的服務器簡單地分紅兩類:場景相關的(如:行走、戰鬥等)以及場景不相關的(如:公會聊天、不受區域限制的貿易等)。常常能夠見到的一種方案是:gate服務器、場景服務器、非場景服務器、聊天管理器、AI服務器以及數據庫代理服務器。以下模型:

 

以上中咱們簡單的講下常見服務器的三種類型功能:

場景服務器:它負責完成主要的遊戲邏輯,這些邏輯包括:角色在遊戲場景中的進入與退出、角色的行走與跑動、角色戰鬥(包括打怪)、任務的認領等。場景服務器設計的好壞是整個遊戲世界服務器性能差別的主要體現,它的設計難度不只僅在於通訊模型方面,更主要的是整個服務器的體系架構和同步機制的設計。

 

非場景服務器:它主要負責完成與遊戲場景不相關的遊戲邏輯,這些邏輯不依靠遊戲的地圖系統也能正常進行,好比公會聊天或世界聊天,之因此把它從場景服務器中獨立出來,是爲了節省場景服務器的CPU和帶寬資源,讓場景服務器可以儘量快地處理那些對遊戲流暢性影響較大的遊戲邏輯。

 

網關服務器: 在類型一種的架構中,玩家在多個地圖跳轉或者場景切換的時候採用跳轉的模式,以此進行跳轉不一樣的服務器。還有一種方式是把這些服務器的節點都經過網關服務器管理,玩家和網關服務器交互,每一個場景或者服務器切換的時候,也有網關服務器統一來交換數據,如此玩家操做會比較流暢。

經過這種類型服務器架構,由於壓力分散了,性能會有明顯提高,負載也更大了,包括目前一些大型的 MMORPG遊戲就是採用此架構。不過每增長一級服務器,狀態機複雜度可能會翻倍,致使研發和找bug的成本上升,這個對開發組挑戰比較大,沒有經驗,很容出錯。

 

三類型(無縫地圖)

 魔獸世界的中無縫地圖,想必你們印象深入,整個世界的移動沒有像以往的遊戲同樣,在切換場景的時候須要loading等待,而是直接行走過去,體驗流暢。

如今的遊戲大地圖採用無縫地圖多數採用的是9宮格的樣式來處理,因爲地圖沒有魔獸世紀那麼大,因此採用單臺服務器多進程處理便可,不過相似魔獸世界這種大世界地圖,必須考慮2個問題:

一、多個地圖節點如何無縫拼接,特別是當地圖節點比較多的時候,如何保證無縫拼接

二、如何支持動態分佈,有些區域人多,有些區域人少,保證服務器資源利用的最大化

爲了解決這個問題,比較以往按照地圖來切割遊戲而言,無縫世界並不存在一塊地圖上面的人有且只由一臺服務器處理了,此時須要一組服務器來處理,每臺 Node服務器用來管理一塊地圖區域,由 NodeMaster(NM)來爲他們提供整體管理。更高層次的 World則提供大陸級別的管理服務。


一個 Node所負責的區域,地理上不必鏈接在一塊兒,能夠統一交給一個Node去管理,而這些區塊在地理上並無聯繫在一塊兒的必要性。一個 Node到底管理哪些區塊,能夠根據遊戲實時運行的負載狀況,定時維護的時候進行更改 NodeMaster 上面的配置。

對象的無縫遷移


玩家A、B、C分別表明3種不一樣的狀態,以及不一樣的遷移方式,咱們分別來看。

  • 玩家A: 玩家A在node1地圖服務器上,由node1控制,若是遷移到node2上,須要將其數據複製到node2上,而後從node1移除。
  • 玩家B: 玩家B在node1和node2中間,此時由node1和node2維護,如果從node1行走到node2的過程當中,會向1請求,同時向2請求,待所有移動過去了再移除。
  • 玩家C:玩家C在node2地圖服務器上,由node2控制,若是遷移到node1上,須要將其數據複製到node1上,而後從node2移除。

具體魔獸世界服務器的分析,篇幅過多,咱們之後再聊。

 

三、房間服務器(遊戲大廳)

房間類玩法和MMORPG有很大的不一樣,在於其在線廣播單元的不肯定性和廣播數量很小。並且須要匹配一臺房間服務器讓少數人進入一個服務器。

這一類遊戲最重要的是其「遊戲大廳」的承載量,每一個「遊戲房間」受邏輯所限,須要維持和廣播的玩家數據是有限的,可是「遊戲大廳」須要維持至關高的在線用戶數,因此通常來講,這種遊戲仍是須要作「分服」的。典型的遊戲就是《英雄聯盟》這一類遊戲了。而「遊戲大廳」裏面最有挑戰性的任務,就是「自動匹配」玩家進入一個「遊戲房間」,這須要對全部在線玩家作搜索和過濾。

玩家先登陸「大廳服務器」,而後選擇組隊遊戲的功能,服務器會通知參與的全部遊戲客戶端,新開一條鏈接到房間服務器上,這樣全部參與的用戶就能在房間服務器裏進行遊戲交互了。

 

4、最後

遊戲行業相對於互聯網應用來講,其開放性和標準化並不完善,這就致使了很其餘行業看遊戲有一種神祕面紗,隱祕而封閉。

形成這個緣由有不少,遊戲業務的複雜性以及受衆羣體小是主要緣由,它不像web應用天生有開源組織和社區基因的支持,也沒有互聯網行業的如此大的受衆面和影響力,除了一些比較出名的遊戲引擎之外其餘的功能組建都是有各個遊戲公司基於本身業務邏輯本身搭建,每一個公司業務方向不一樣又加大了知識的流通以及標準的創建,這對整個生態的發展已經產生了制約,特別是那些想加入遊戲行業的新人來講,准入門檻較高,網上可找到的學習資料也不多。

這種現象目前正在發生改變,除了受衆羣體愈來愈大和豐富之外,還有一些技術組織正在推動整個社區的進步。

好比每一年一度的unity 技術大會,以及其餘優秀的開源引擎都在積極推動整個遊戲社區的建立,除了吸引更多優秀的技術人才和團隊加入,這一切都讓遊戲行業變得愈來愈開放和規範,讓行業內的知識也得以流通和繼承。固然了,也指望每一個遊戲人可以加入進來,分享本身的知識,讓自由開放的共享精神傳承每一個地方。

 

引用:

http://www.skywind.me/blog/archives/1265

http://gcloud.qq.com/forum/topic/56a0bac3a90d8b775e8f3c1b

----------------------------------------end-------------------------------------

關注我的成長和遊戲研發,致力推進國內遊戲社區的成長與進步。

想了解更多有料的遊戲技術,請關注個人公衆號,原創以及獨到。

相關文章
相關標籤/搜索