1. 程式人生 > >【轉】服務器結構探討 -- 簡單的世界服實現

【轉】服務器結構探討 -- 簡單的世界服實現

導致 承擔 夢幻 其他 href 請求 先生 數據處理 serve

轉自 http://blog.csdn.net/lfhfut/article/details/1779848

  討論了這麽久我們一直都還沒有進入遊戲世界服務器內部,現在就讓我們來窺探一下裏面的結構吧。

  對於現在大多數MMORPG來說,遊戲服務器要處理的基本邏輯有移動、聊天、技能、物品、任務和生物等,另外還有地圖管理與消息廣播來對其他高級功能做支撐。如縱隊、好友、公會、戰場和副本等,這些都是通過基本邏輯功能組合或擴展而成。

  在所有這些基礎邏輯中,與我們要討論的服務器結構關系最緊密的當屬地圖管理方式。決定了地圖的管理方式也就決定了我們的服務器結構,我們仍然先從最簡單的實現方式開始說起。

  回想一下我們曾戰鬥過無數個夜晚的暗黑破壞神,整個暗黑的世界被分為了若幹個獨立的小地圖,當我們在地圖間穿越時,一般都要經過一個叫做傳送門的裝置。世界中有些地圖間雖然在地理上是直接相連的,但我們發現其遊戲內部的邏輯卻是完全隔離的。可以這樣認為,一塊地圖就是一個獨立的數據處理單元。

  既然如此,我們就把每塊地圖都當作是一臺獨立的服務器,他提供了在這塊地圖上遊戲時的所有邏輯功能,至於內部結構如何劃分我們暫不理會,先把他當作一個黑盒子吧。

  當兩個人合作做一件事時,我們可以以對等的關系相互協商著來做,而且一般也都不會有什麽問題。當人數增加到三個時,我們對等的合作關系可能會有些復雜,因為我們每個人都同時要與另兩個人合作協商。正如俗語所說的那樣,三個和尚可能會碰到沒水喝的情況。當人數繼續增加,情況就變得不那麽簡單了,我們得需要一個管理者來對我們的工作進行分工、協調。遊戲的地圖服務器之間也是這麽回事。

  一般來說,我們的遊戲世界不可能會只有一塊或者兩塊小地圖,那順理成章的,也就需要一個地圖管理者。先稱它為遊戲世界的中心服務器吧,畢竟是管理者嘛,大家都以它為中心。

  中心服務器主要維護一張地圖ID到地圖服務器地址的映射表。當我們要進入某張地圖時,會從中心服上取得該地圖的IP和port告訴客戶端,客戶端主動去連接,這樣進入他想要去的遊戲地圖。在整個遊戲過程中,客戶端始終只會與一臺地圖服務器保持連接,當要切換地圖的時候,在獲取到新地圖的地址後,會先與當前地圖斷開連接,再進入新的地圖,這樣保證玩家數據在服務器上只有一份。

  我們來看看結構圖是怎樣的:

   中心服務器
/ / / /
/ / / /
 登錄服 地圖1 地圖2 地圖n
/ | / /
/ | / /
    客戶端

  很簡單,不是嗎。但是簡單並不表示功能上會有什麽損失,簡單也更不能表示遊戲不能賺錢。早期不少遊戲也確實采用的就是這種簡單結構。

  都已經看出來了,這種每切換一次地圖就要重新連接服務器的方式實在是不夠優雅,而且在實際遊戲運營中也發現,地圖切換導致的卡號,復制裝備等問題非常多,這裏完全就是一個事故多發地段,如何避免這種頻繁的連接操作呢?

  最直接的方法就是把那個圖倒轉過來就行了。客戶端只需要連接到中心服上,所有到地圖服務器的數據都由中心服來轉發。很完美的解決方案,不是嗎?

  這種結構在實際的部署中也遇到了一些挑戰。對於一般的MMORPG服務器來說,單臺服務器的承載量平均在2000左右,如果你的服務器很不幸地只能帶1000人,沒關系,不少遊戲都是如此;如果你的服務器上跑了3000多玩家依然比較流暢,那你可以自豪地告訴你的策劃,多設計些大量消耗服務器資料的玩法吧,比如大型國戰、公會戰爭等。

  2000人,似乎我們的策劃朋友們不大願意接受這個數字。我們將地圖服務器分開來原來也是想將負載分開,以多帶些客戶端,現在要所有的連接都從中心服上轉發,那連接數又遇到單臺服務器的可最大承載量的瓶頸了。

  這裏有必要再解釋下這個數字。我知道,有人一定會說,才帶2000人,那是你水平不行,我隨便寫個TCP服務器都可帶個五六千連接。問題恰恰在於你是隨便寫的,而MMORPG的服務器是復雜設計的。如果一個演示socket API用的echo服務器就能滿足MMOG服務器的需求,那寫服務器該是件多麽愜意的事啊。

  但我們所遇到的事實是,服務器收到一個移動包後,要向周圍所有人廣播,而不是echo服務器那樣簡單的回應;服務器在收到一個連接斷開通知時要向很多人通知玩家退出事件,並將該玩家的資料寫入數據庫,而不是echo服務器那樣什麽都不需要做;服務器在收到一個物品使用請求包後要做一系列的邏輯判斷以檢查玩家有沒有作弊;服務器上還啟動著很多定時器用來更新遊戲世界的各種狀態......

  其實這麽一比較,我們也看出資料消耗的所在了:服務器上大量的復雜的邏輯處理。再回過頭來看看我們想要實現的結構,我們既想要有一個唯一的入口,使得客戶端不用頻繁改變連接,又希望這個唯一入口的負載不會太大,以致於接受不了多少連接。

  仔細看一看這個需求,我們想要的僅僅只是一臺管理連接的服務器,並不打算讓他承擔太多的遊戲邏輯。既然如此,那五六千個連接也還有滿足我們的要求。至少在現在來說,一個遊戲世界內,也就是一組服務器內同時有五六千個在線的玩家還是件讓人很興奮的事。事實上,在大多數遊戲的大部分時間裏,這個數字也是很讓人眼紅的。

  什麽?你說夢幻、魔獸還有史先生的那個什麽征途遠不止這麽點人了!噢,我說的是大多數,是大多數,不包括那些明顯。你知道大陸現在有多少遊戲在運營嗎?或許你又該說,我們不該在一開始就把自己的目標定的太低!好吧,我們還是先不談這個。

  繼續我們的結構討論。一般來說,我們把這臺負責連接管理的服務器稱為網關服務器,因為內部的數據都要通過這個網關才能出去,不過從這臺服務器提供的功能來看,稱其為反向代理服務器可能更合適。我們也不在這個名字上糾纏了,就按大家通用的叫法,還是稱他為網關服務器吧。

  網關之後的結構我們依然可以采用之前描述的方案,只是,似乎並沒有必要為每一個地圖都開一個獨立的監聽端口了。我們可以試著對地圖進行一些劃分,由一個Master Server來管理一些更小的Zone Server,玩家通過網關連接到Master Server上,而實際與地圖有關的邏輯是分派給更小的Zone Server去處理。

  最後的結構看起來大概是這樣的:

Zone Server Zone Server
/ /
/ /
Master Server Master Server
/ / /
/ / /
Gateway Server / /
| / / /
| / / /
| Center Server
|
|
Client

【轉】服務器結構探討 -- 簡單的世界服實現