遊戲伺服器架構通識
之前有網友問遊戲伺服器和網站伺服器之間區別的問題,用我以前寫的一篇講座PPT整理後作出了回答,反響還不錯。今天特將原文整理如下,以饗網友。
前言
這節講座里,我們將從遊戲伺服器發展的簡單歷程出發,鳥瞰一下目前大多數的遊戲伺服器架構。
這裡儘可能的避免陷入細節的技術問題,而是從技術進化的結果狀態,反推原始問題是什麼。希望能通過這個過程,解釋清楚遊戲伺服器是在解決什麼問題,痛點到底在哪裡。
一、早期網遊伺服器。
蠻荒時期的遊戲伺服器框架我們一筆帶過,那時的遊戲伺服器和一個小Web服務沒有區別。
蠻荒時代的伺服器只負責存儲玩家賬號、數據、轉發場景內其他玩家的行為。很多移動、使用技能等關鍵邏輯在伺服器上根本沒有。隨意就能用變速齒輪改變遊戲速度。
從《傳奇》的時代開始,遊戲伺服器就不再是簡單的上傳存檔、下載存檔、訪問頁面而已。遊戲伺服器內部出現了遊戲邏輯,既能用於同步每個玩家看到的世界,又能讓邏輯與客戶端分離,避免早期的網路遊戲那種毫無防範的邏輯體系(對外掛防禦能力為0)。
如圖,客戶端通過某種形式驗證登陸以後,就和伺服器通過TCP直接相連了。這種伺服器的承載能力不高,但那時在遊戲邏輯上也務求簡化,把負載減少到極致。
· 例如:1、玩家看不到怪物的血量,或者只能看到正在打的怪物的血量。2、地圖有格子的概念,每個格子只能有一個單位,極大限制了同屏人數。
由於邏輯盡量簡化,雖然這時的伺服器邏輯服務都是單進程單線程的,但是也足夠表現交互的感受。
這種架構奇怪的地方是處理網路連接數據傳輸的壓力和邏輯處理的壓力在同一個伺服器上(存儲模塊可能也在同一個進程),就算邏輯處理壓力為0,承載人數也高不到哪去。
雖然這時的遊戲伺服器設計很簡陋,但是網遊第一次給了玩家真實世界的感受。單服人數不足的問題可以靠開多組伺服器實現,所以曾經出現了幾百上千組伺服器的輝煌時代。
二、早期遊戲伺服器的改進版本
當開發者們有了初步經驗以後,新作品的開發,自然而然的過渡到了如下的形式:
遊戲邏輯服務依然是在一台伺服器上,單進程(邏輯處理本身肯定是在一個線程中,可以有子線程負責內網通信)。但是我們自然的想到,存儲負載和網路連接負載可以從邏輯服上拆出來。
連接伺服器負責把客戶端和伺服器之間的消息轉化為伺服器之間的消息,可以順便做一些加解密的工作。
這一點小改動極大提高了單服連接人數的上限。但是玩家要求提高了,空出來的性能很快被豐富的遊戲系統吃掉了。
由於連接伺服器本身沒有時序性,很容易做分散式的(其實大部分遊戲還是只用一個連接服),存儲服務不要求高實時性,高峰期存檔間隔可以稍長一些,不會對遊戲服造成影響。
三、成熟形態的伺服器框架
邏輯伺服器的負載均攤方法一:按照功能劃分多個伺服器進程
邏輯伺服器的負載均攤方法二:按照場景劃分多個伺服器進程
對遊戲伺服器歷史有了基本了解後,成熟形態的遊戲伺服器很容易理解。簡單來說,就是把邏輯伺服器單個進程的壓力分攤到多個伺服器。
難點在邏輯的設計上,要像做手術一樣把本來是一體的功能切開,並抽象出若干個API來保持聯繫(伺服器之間是TCP連接)。
在分解時,要找聯繫相對最薄弱的環節入手,比如場景和場景之間分開、單獨抽出聊天服務、組隊服務、好友服務。
無論如何分解,最終結果只能是有限個服務。而且分解的越細,開發難度就越大。因為跨伺服器邏輯是把簡單的同步邏輯變成了非同步Callback邏輯,而且容易出現時序問題等不易測試的問題。
單個場景服務幾乎是無法分解的。分解單個場景難度巨大以至於出現了BigWorld引擎來專門的解決場景分割問題,後面會談到。
這種成熟形態的遊戲伺服器已經能滿足現實中99%的頻繁交互類網遊需求,是大型MMO端游、頁游的主流形式。
當然有實力的公司在這個基礎上會做很多改動,實現動態開闢副本、相位技術等等,但是萬變不離其宗,其本質和上圖沒有什麼區別。
附:開房間式的網路遊戲
開房間式的網路遊戲也是遊戲的一個重要分支,英雄聯盟、DOTA、很多手游例如皇室戰爭、王者榮耀等等。
這種遊戲房間之間幾乎沒有交互,只有大廳內有交互,可以理解為原始形態的遊戲伺服器的平行擴展。
房間式遊戲擴展難度較小,只是需要根據玩家數量動態擴展遊戲房間的數量、伺服器數量。很像網站的架構。
這種遊戲架構最最適合放在雲平台上,設計合理的話,它可能遇到的問題和大型網站幾乎一模一樣。不需要特別的討論它們。
只是,畢竟遊戲不都是開房間的玩法。
小結:遊戲伺服器框架特點
1、真正的數據都在內存中,資料庫性能不那麼重要
· 註:很多大型遊戲採用了共享內存,避免宕機時損失過大。
2、單CPU性能比CPU數量重要的多。
3、目前有很多遊戲,特別是手游,使用Redis讀寫代替內存讀寫,甚至也有用Mongo的。
4、開新服、舊區合服的情況,非常適合雲平台。
五、先進伺服器框架
· 先進伺服器框架1 BigWorld
BigWorld引擎的代表作:
· 中國:《天下貳 》《天下叄》等等數十款,網易對BigWorld的實用化貢獻很大。
· 國際:《魔獸世界》早期版本,《坦克世界》,《戰爭雷霆》
BigWorld的核心理念,要回到上面講過的場景分割問題。
BigWorld利用平面切分的原理,將場景劃分為小塊,不同的塊可以運行在不同的伺服器上。而且塊的劃分是動態的,根據玩家密集程度、數量動態調整塊的大小。。
具體技術上,使用了Actor模型,要求每個對象都是獨立的Entity,對象之間只能通過消息協作,嚴格限制對象之間的直接交互。
後來隨著手游的崛起、端游的衰落、網遊玩法向多元化發展,這一系列的變化,導致BigWorld引擎很快就衰落了。
BigWorld引擎從曾經的大紅大紫,到現在的無人問津,反映出遊戲伺服器技術的發展趨勢。BigWorld的強制Actor模型,實際上是犧牲了開發效率,換取了伺服器可擴展性。
理論上單服承載人數可以達到百萬級別。但是遊戲的業務邏輯的修改很頻繁,開發效率低下是遊戲設計師不能承受之重。
這種架構天生就是為雲計算準備的,而且單個物理機承載量十分有限,每個遊戲大區都需要大量實體機。
如果BigWorld成功…… 可惜的是,它和實際市場的發展趨勢背道而馳了。
遊戲開發相比電商系統,項目規模小几個數量級,但是相對的,迭代速度要快幾倍。項目之間如果類型不同或是玩法有差異,能復用的代碼並不多。
聊聊十萬行代碼。遊戲伺服器開發速度受美術資源製作速度、客戶端開發速度制約。近幾年我猜測伺服器方面並不會有大的技術革新。
遊戲開發未來的趨勢是多元化、低門檻化、大眾化。很長一段時間內BigWorld這種大怪獸級別的引擎不會再崛起。
分散式框架的崛起時間點,無論如何,也在VR技術成熟之後了。
· 先進伺服器框架2、Skynet
Skynet是新興的一種通用型伺服器框架(完全開源),它遊走在傳統不易分布伺服器和分散式伺服器之間。
它是一種泛用型框架,不僅能很好的作為遊戲伺服器框架使用,而且用來搭建HTTP服務也具有驚人的性能(幾百行代碼的簡單HTTP實現,能達到nginx 60%的性能)。
矛盾的是,由於它對腳本虛擬機做了一些重要的Hack,導致它完全綁定在了Lua這一種語言上。
Skynet原理闡述:
把服務抽象為微服務,一個系統內可以建立成千上萬個微服務,Skynet調度m個線程(m=CPU核心數)、處理n個微服務各自的事件。
由於n個微服務在同一個進程內,可以達到0延遲的內部通信(極端情況下無拷貝)
同時Lua虛擬機又提供了沙盒機制,微服務之間的Lua邏輯代碼不會有任何干擾,必要的時候又可以在C語言層面、Lua沙盒之外共享數據。
由於服務本身有良好的隔離性,可以較為方便的把服務部署到多物理機上(考慮到性能問題,不能像BigWorld那樣任意部署)。
Skynet這種架構已經在Lua體系的遊戲公司內大量使用(以網易係為代表),悄無聲息的滲透到其他公司里。(和Lua語言當年的情況有點像,是金子總會發光的。)
六、先進伺服器框架3、以Go語言為主的其他框架
Go語言的goroutine特性,給遊戲開發者帶來巨大的想像空間。
在Go語言的基礎上,很容易出現更好的房間式遊戲框架、類似Skynet的框架、改進型的傳統框架。
但是可以大膽預測,最終實現的效果不會超過erlang、skynet這類框架的範圍。這是因為遊戲業務本身的特性決定的。
結束語
本文簡要探討了十幾二十年來,主流伺服器框架的發展脈絡,以MMO-RPG這種最具代表性的網遊類型為主(同時MMO對伺服器架構的挑戰也是最大的),兼談到一些其他類型的遊戲。由於遊戲類型多種多樣,各個國家和地區的開發商所偏好的架構方式也大有不同,文中難免掛一漏萬,但不太影響整體脈絡,也不影響對網遊伺服器的核心問題的總結——邏輯拆分。
期待讀者們提出批評和建議。
————————————————————————————————
對遊戲開發感興趣的同學,歡迎圍觀我們:【皮皮關遊戲開發教育】 線下教育自不必說,還會定期更新各種教程,乾貨。在你學習進步的路上,有皮皮關陪你!~
我們的官網地址:http://levelpp.com/
我們的遊戲開發技術交流群:610475807
我們的微信公眾號:levelpp
推薦閱讀:
※類QQ的系統後台服務端怎麼做性能測試?怎麼模擬那麼大的並發量?
※維基百科的伺服器架構是怎樣的?是如何支撐起如此高的訪問量的?
※Netty怎麼保持長連接?
※在集群中部署多個伺服器如何解決SESSION問題?