手遊頁遊和端遊的服務端本質上沒區別,區別的是遊戲類型。前端
類型1:卡牌、跑酷等弱交互服務端web
卡牌跑酷類由於交互弱,玩家和玩家之間不須要實時面對面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人之內,所以能夠得到更爲實時的遊戲體驗,讓玩家玩的更加爽快。
說了那麼多的遊戲服務器類型,其實也差很少了,剩下的類型你們拼湊一下其實也就是這個樣子而已。遊戲服務端經歷了那麼多結構上的變遷,內部開發模式是否依然不變?到底是繼續延續傳統的開發方式?仍是有了更多突破性的方法?經歷那麼屢次架構變遷,後面是否有共通的邏輯?將來的發展還會存在哪些困難?遊戲服務端開發如何達到最終的彼岸?