遊戲後臺開發九問(騰訊技術分享實錄)

[導讀]騰訊遊戲訊,7月30日消息,第九屆中國遊戲商務大會網頁遊戲論壇30日在上海浦東嘉裏大酒店展進行相關主題論壇活動。

30日,在上海chinajoy嘉裏酒店進行了遊戲開發者大會,騰訊遊戲的研發部助力總經理聶志明進行了演講。

他爲大家演講的題目是“遊戲後臺開發中的九個選擇”,他解釋,使用這個標題的原因,是因爲我們在生活中總會遇到很多選擇,這個道理同樣適用在遊戲開發中。

這九個選擇分別是:

第一,選擇什麼樣的架構。

第二,選擇單線程還是多線程。

第三,如何在遊戲中使用腳本。

第四,如何處理網絡通訊。

第五,如何處理遊戲通信協議。

第六,如何設計存儲結構。

第七,如何設計網絡同步。

第八,如何定義性能基準。

第九,如何在不同項目間進行代碼複用。

聶志明先生在他的PPT裏詳細地爲大家講解了這九個問題,具體情況請參看演講實錄。

以下是演講實錄:

聶志明:大家好!我們現在開始演講,我先自我介紹,我是騰訊遊戲研發部助理總經理。我今天的題目是“遊戲後臺開發中的九個選擇”,爲什麼用這個題目?在生活中我們有很多選擇,對這些選擇的不同處理方式會決定不同的品質,我們在遊戲開發裏面會遇到很多選擇,我今天說九個,但不一定每個人都碰得到,我在這裏會把一些經驗給大家分享一下。

首先介紹一下在騰訊開發跟別的公司會有不同,在我內部遵從兩個崗位,每個公司裏面是按照不同模塊來分。爲什麼會這樣分?前臺是通過便,後臺講究的是不便,我們不是追求新的技術,而是解決問題。

下面我開始演講,這是北京最盛名的一座橋,每次都不知道怎麼走,越來越複雜。我們每天都會遇到很多選擇,所以導致人也不是很愉快。

我現在來講九個選擇,從Q1到Q9,後面一一按照這個順序做個闡述。


第一,選擇什麼樣的架構?

其實是SNS特點決定的,不同的特點決定不同的架構。玩發圍繞的是玩家之間偏真實的關係鏈,位置對玩家是不重要的,玩家之間沒有物理上的距離概念,SNSGame是大世界的模式,通用大世界方案的系統必須平行發展。MMO的特點,前幾年是一個發展重點,很多人瞭解也不是很多,它的特點是存在世界地圖,位置很重要,有地形概念,每個玩家都有自己的物理座標。交互頻繁,邏輯複雜,交互的實時性要求高,嚴重依賴於預先設計的遊戲內容。小世界有小世界的好處。第一易於就近部署及,減輕國內網絡複雜與MMO對網絡要求高的矛盾。大家知道網絡有很多問題,大家知道問題也解決不了。對MMO來講,是一個很高的類型,所以會用小世界。

通過分區服務,降低了因爲架構導致的運營問題的嚴重性,小世界的內部在架構上也需要有一定的可伸縮性,這取決於遊戲的設計。並不是所有的小世界只有一臺服務器搞定,因爲它的元素、它的特點對它也會有不同的要求。

在我選擇這種架構的時候,我們會有原則,選擇什麼樣的架構取決於遊戲自身的設計,這取決於某些特點,並不是所有服務都有同樣的需求,並不是大世界就好,小世界就不行。我們不從純技術角度追求大世界的架構,大世界需要遊戲內容的支持,通常美術策劃無法支撐百萬在線的世界,這是最根本的原因。大世界在架構上有困難,但這是部分不可克服的。

我講大家非常熟悉的一個例子,通常最複雜的大區概念,大區通常是做帳號,服務器在服務器裏面按角色區分。線,就是有的遊戲有,有的遊戲沒有,在這些線裏面只是爲了擴展這個世界的流量上線,線目前來說只是一個方便,這是一個樣對複雜的示意部署視圖(PPT)。

我們看一個架構,如果展開來講,左邊是一些輔助服務,右邊的Worldsvr像公會的那種會放在這個裏面,加在服務器上面,不同的遊戲會有不同的處理。這是一個簡單的示意圖,在不同的遊戲裏面會有不同的區分。


第二,選擇單線程還是多線程?

不同的公司會有不同的做法,這個問題並不是所有人都碰到,也有個概率,但是大家也會有爭論。爭論的原因,通常是雙方關注的重點不同,單線程程序的執行只有一條主線,容易跟蹤、調試和定位。我們騰訊也不是一定說要這樣選擇,我們理由非常理由,單線程加異步模式可以提供更好的性能,我們會選擇單線程模式。現在我們遊戲開發週期很長,在漫長的運行週期裏面每週都會更新,交接過程中會有問題的,使用多線程容易導致問題。這個時候我們會進行一些處理,我們對裏面的要求角度來看,運行的週期很長、節奏很快,爲了達到要求我們可以想更簡便的方式。

新形勢,對我們也是有一些影響,現在有一些四核以上的CPU出現,這個時候我們會嘗試把一些通用的服務,把相對固定的進程變成簡單化,這是一個新趨勢。

這是適應新趨勢的原則,只在必須的時候才使用多多線程,如果使用了多線程,儘量減少線程間的交互需求,這樣我們就好把握。


第三,如何在遊戲中使用腳本?

在遊戲開發中通常大家都會使用一些腳本。客戶端對腳本的需求非常明顯,這裏主要討論服務器端。兩種使用腳本的方式:一種是C/C++的框架,主要邏輯用C/++編寫,腳本用來做一些局部擴展。C/C++的框架,主要邏輯用腳本來編寫,耗性能的地方用C/C++決定的。

使用腳本的原則,腳本是一種膠水語言,通常用來隔離變化,易變化的邏輯用腳本實現,快速響應。一般情況下是說這個性能高,那個性能低,上面兩種方法沒有對錯之分,取決於兩點,開發團隊成員的能力,對不同語言的掌握程度;公司或者項目組的導向,偏重性能還是偏重開發速度,如果是創業型的團隊,對性能方面要求多一些,怎麼樣把遊戲做好纔是最重要的。


第四,如何處理網絡通訊?

其實網絡通信本身是非常複雜的事情,目前的開發環境已經提供了相對來講簡單得多的編程接口,但是網絡程序還是需要處理很多的問題。

兩種處理方式:一種是跟遊戲服務器耦合帶一起,遊戲服務器既處理問落接入相關的邏輯,也處理遊戲邏輯。一種是把網絡通信部分剝離住來,向遊戲服務器提供一種以消息爲單位的、非阻塞的、有Qos能力的中間服務,遊戲服務器看不到網絡的細節。

我們選擇第二種好處,是基於這樣的考慮,首先簡化了遊戲服務器的處理邏輯,降低了編程的難度。更易於提升後臺整體的處理性能,不同部分可以獨立的優化,因爲它可以不斷的優化和在不同項目裏面去繼承的。

這是非常簡單的一張示意圖,我們會有一個界面,在客戶端和服務器端給它不同的接口,會有不同的形式,看不到網絡的問題,而且都是非阻塞的形式,面向消息的服務,類似於有保障的、可持續的服務。


第五,如何處理遊戲通信協議?

協議分兩大類:文本協議和二進制協議,這是兩個非常典型的例子,左邊是UDP,非常高興。右邊是文本的協議,都是文字。文本協議直觀,版本兼容性好,但是效率低。其實對於遊戲來講,我們最好能夠做到不同的版本都可以玩,不強調所有的客戶端都去升級,這對運營商有非常強的週期,這對運營商來說有很大的挑戰。版本兼容性問題其實是我們在通信協議的時候,都需要重點考慮的。二進制協議效率高,但是不直觀,版本兼容性處理相對複雜。

Web相關的遊戲根據與瀏覽器交互的方式可能採用文本協議,基於效率原因,C/S類型的遊戲通常採用二進制協議。

下面我會介紹騰訊的經驗,遊戲服務器是時鐘消息和網絡消息驅動的,大部分代碼都是接受消息,或者接納,其實有很多的解碼、編碼、代碼佔了相當大的比例。我們可以把協議做一個區分,就變成一個消息的協議描述,然後生成工具,然後得到網絡協議處理代碼。

這是我們的做法,我們自己定義了一套協議描述方法,並實現了相應了工具集。我們這個協議重點會有所不同,在於高性能、與C/C++的無縫結合以及多協議版本共存能力。利用我們這個版本來描述協議,不斷在上面添加新的內容,但是其實可以進入到所有的低版本的客戶端協議,不需要開發者做任何處理,它會自動生成。類似的方式大家可以看Google protobuf orFacebook thrift。


第六,如何設計存儲結構。

從遊戲來講,所有的在線遊戲通常使用數據庫來存儲用戶數據。通常MMO使用關係型數據庫來存儲數據,後面主要針對MMO進行存儲方式的討論。會有兩種方式:一種是把遊戲的每一個數據對象的屬性看成一個單獨字段,遵循RDBMS的要求來設計數據庫表和索引,儘量符合3NF。以MMO爲例,有帳號表、角色基本信息表、物品表、裝備表等等,這是一種方式。

還有一種方式更具體,角色的列表類數據儘量採用blob來存儲而不是另一個表。原則是這些列表數據只被角色自身所擁有,就是這個玩家所擁有,其他玩家不會擁有個數據,它的生命週期跟玩家是一致的,不存在其他的交叉擁有情況,技能、物品、裝備、任務、好友等等都屬於這種情況。

優點是存儲表結構簡單,通常幾張表就可以玩一個遊戲,不超過10個。存取交互簡單,角色登錄或者推出時通常只需要存取一到二條記錄。同一個角色的數據易於保持一致,易於多版本數據共存。我們把這些數據存到數據庫的時候,會把編碼存到數據庫裏面。所以在數據庫裏面做完的數據可能會不一樣,不過不會影響,它會共存。

這種方式也會有缺點,數據維護工具、客服工具實現相對複雜,需要提供特殊的API來操作數據。如果手上工具是通用的,可能比以前要直白一點。某些類型的統計相對要麻煩一些,有些常用的數據,比如說角色的等級,在這方面可以用一些方式解決你的問題。

舉個例子,在MMOG這塊,存儲角色的概要信息,包括名字、基本屬性等,用於顯示角色列表和防止重名。還有存儲角色的詳細信息,存儲帳號的倉庫信息,存儲公會的信息。

新趨勢的影響,就是Nosql數據庫,性能高,存在好的開源實現,遊戲的數據訪問多爲唯一鍵訪問,很少複雜的Query,符合Nosql數據庫的特點。後面在遊戲應用上,可能也會涉及到。


第七,如何設計網絡同步?

網絡同步面臨的主要問題:第一如何減少網絡波動對同步的影響;第二如何減少外掛對同步的破壞。如果沒有外掛,網絡幾大問題沒有服務器去運行。這兩個問題單獨都好解決,但是在一起比較難解決。我們解決這兩個問題,會遵循幾個原則:第一網絡條件好的玩家獲得好的體驗;第二網絡條件差的玩家儘可能獲得好一些的體驗,但不能拖累其他玩家的體驗;第三外掛不能在網絡同步方面獲得持續的好處。對外掛方面,玩一個遊戲是一個人,或者說非人類不清楚,所以說外掛不能在網絡同步獲得持續的好處。

爲了解決問題我們有一些基本方法:首先要探測玩家的網絡質量;第二在玩家機器與服務器之間進行時鐘同步;第三基於遊戲特點,設計合理的同步機制。像競技類的遊戲,都是根據它的某些特點決定的,這是需要我們權衡考慮的。這裏強調一點,在外掛獲得好處,跟玩家體驗時間做一個折中,你要保證外掛持續得到源源不斷的好處,這樣外掛就會上去。對於探測、時鐘同步都需要控制好。


第八,如何定義性能基準?

做遊戲開發通常不太注重事先對於性能的規劃,多以結果作爲目標,基本上是看後來測試出來的性能,能優化則優化。性能基準包括客戶端和服務器,客戶端的性能基準與遊戲的目標市場有關。在服務器當中我們可以分析出來服務器能支撐多少用戶?我們分解一下,制約性能的因素,網絡IO/磁盤IO/內存/CPU。

具體的方法,可以通過經驗的方式,或者計算的方式來確確定理論上限。網絡IO,可以分析,取悅於由遊戲類型、遊戲設計所形成的業務模型,可估算。內存,相對來講更簡單,取決於用到的主要數據結構,相對來講更聚焦,更能估算出來支撐多少人。CPU計算能力,其實也不是計算,需要更多對CPU的支撐,簡單的方式,這個遊戲取決於遊戲類型導致的邏輯複雜性。推過這三點,可以有一個目標,大概需要多少人。

我們的數據,以實時列MMOG來講,單一物理服務器1CPU,2核心,支撐3000-4000在線。平均每用戶流量12-20Kbps。


第九,如何在不同項目間進行代碼複用?

當一個公司內在不止一個項目在開發、運營時,複用的想法的產生是自然而然的。簡單的把上一個心目的可用代碼拷貝過來自行維護是最簡單的方式,但是會導致同一個功能有N種實現變體,每個變體都解決一部分問題。把共用的代碼收歸一個杜立德組織來開發和維護,形成公共組件,能夠解決上述的問題,但是又會帶來新的問題。要解決這些問題,也很難有一些具體的方法,有幾個原則,以服務、進程、庫來提供。提供充分的工具,滿足調試、驗證、部署、運營等需求,如果推廣好對你有很大的關係。最後還有充分的提供擴展能力,可以降低組件開發的壓力。

我這邊就講到這裏,九個問題,並不一定所有問題都會碰到,但希望這些問題對大家有所幫助。謝謝!

發佈了169 篇原創文章 · 獲贊 97 · 訪問量 46萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章