近年來,我身邊的朋友有很多都從web轉向了游戲開發(fā)。他們以前都沒有做過游戲服務器開發(fā),更談不上什么經驗,而從網上找的例子或游戲方面的知識,又是那么的少,那么的零散。當他們進入游戲公司時,顯得一臉茫然。如果是大公司還好點,起碼有人帶帶,能學點經驗,但是有些人是直接進入了小公司,甚至這些小公司只有他一個后臺。他們一肩扛起了公司的游戲后端的研發(fā),也扛起了公司的成敗。他們也非常盡力,他們也想把游戲的后端做好。可是就是因為沒什么經驗,剛開始時以為做游戲服務器和做web差不多,但是經過一段時間之后,才發(fā)現(xiàn)代碼太多,太亂了,一看代碼都想重構,都是踩著坑往前走。
這里我把一些游戲開發(fā)方面的東西整理一下,希望能對那些想做游戲服務器開發(fā)的朋友有所幫助。
首先,要明確一點,做游戲服務器開發(fā)和做傳統(tǒng)的web開發(fā)有著本質的區(qū)別。游戲服務器開發(fā),如果沒有經驗,一開始根本沒有一個明確清析的目標,不像web那樣,有些明確的MVC架構,往往就是為了盡快滿足策劃的需求,盡快的實現(xiàn)功能,盡快能讓游戲跑起來。但是隨著功能越來越多,在老代碼上面修改的越來越頻繁,游戲測試時暴露出來的一堆bug,更讓人覺得束手無策,這個時候我們想到了重構,想到了架構的設計。
游戲的構架設計非常重要,好的構架代碼清析,責任明確,擴展性強,易調試。這些會為我們的開發(fā)省去不少時間。那要怎么樣設計游戲的構架呢?可能每個游戲都不一樣,但是本質上還是差不多的。
對于游戲服務器的構架設計,我們首先要了解游戲的服務器構架都有什么組成的?一款游戲到上線,需要具備哪些功能?有些人可能會說,只要讓游戲跑起來,訪問服務器不出問題不就行了嗎?答案是不行的,游戲構架本身代表的是一個體系,它包括:
這一系統(tǒng)的東西都是不可少的,它們共同服務于游戲的整個運營過程。我們一點點來介紹各個系統(tǒng)的功能。
一,系統(tǒng)初始化
系統(tǒng)初始化是在沒有客戶端連接的時候,服務器啟動時所需要做的工作?;旧暇褪桥渲梦募淖x取,初始化系統(tǒng)參數。
但是我們必須要考慮的是:
系統(tǒng)初始化需要的參數配置在哪兒,是配置在本地服務器,還是配置在數據庫;
服務器啟動的時候去數據庫??;
配置的修改需不需要重啟服務器等。
二,游戲邏輯
游戲邏輯是游戲的核心功能實現(xiàn),也是整個游戲的服務中心,它被開發(fā)的好壞,直接決定了游戲服務器在運行中的性能。那在游戲邏輯的開發(fā)中我們要注意些什么呢?
游戲是一種網絡交互比較強的業(yè)務,好的底層通信,可以最大化游戲的性能,增加單臺服務器處理的同時在線人數,給游戲帶來更好的體驗,至少不容易出現(xiàn)因為網絡層導致的數據交互卡頓的現(xiàn)象。在這里我推薦使用Netty,它是目前最流行的NIO框架,它的用法可以在我之前的文章中查看,這里不再多說了。
有人疑問,代碼也需要分層次?這個是當然了,不同的代碼,代表了不同的功能實現(xiàn)?,F(xiàn)在的開發(fā)語言都是面向對象的,如果我們不加思考,不加整理的把功能代碼亂堆一起,起始看起來是快速實現(xiàn)了功能,但是到后期,如果要修改需求,或在原來的代碼上增加新的需求,那真是被自己打敗了。所以代碼一定要分層,主要有以下幾層:
三,數據庫系統(tǒng)
數據庫是存儲數據庫的核心,但是游戲數據在存儲到數據庫的時候會經過網絡和磁盤的IO,它的訪問速度相對于內存來說是很慢的。一般來說,每次訪問數據庫都要和數據庫建立連接,訪問完成之后,為了節(jié)省數據庫的連接資源,要再把連接斷開。
這樣無形中又為服務器增加了開銷,在大量的數據訪問時,可能會更慢,而游戲又是要求低延時的,這時該怎么辦呢?我們想到了數據庫連接池,即把訪問數據庫的連接放到一個地方管理,用完我不斷開,用的時候去那拿,用完再放回去。這樣不用每次都建立新的連接了。
但是如果要我們自己去實現(xiàn)一套連接池管理組件的話,需要時間不說,對技術的把控也是一個考驗,還要再經過測試等等,幸好互聯(lián)網開源的今天,有一些現(xiàn)成的可以使用,這里推薦Mybatis,即實現(xiàn)了代碼與SQL的分離,又有足夠的SQL編寫的靈活性,是一個不錯的選擇。
四,緩存系統(tǒng)
游戲中,客戶端與服務器的交互是要求低延遲的,延遲越低,用戶體驗越好。像之前說過的一樣,低延遲就是要求服務器處理業(yè)務盡量的快,客戶端一個請求過來,要在最短的時間內響應結果,最低不得超過500ms,因為加上來回的網絡傳輸耗時,基本上就是600ms-到700ms了,再長玩家就會覺得游戲卡了。
如果直接從數據庫中取數據,處理完之后再存回數據庫的話,這個性能是跟不上的。在服務器,數據在內存中處理是最快的,所以我們要把一部分常用的數據提前加載到內存中,比如說游戲數據配置表,經常登陸的玩家數據等。這樣在處理業(yè)務時,就不用走數據庫了,直接從內存中取就可以了,速度更快。
游戲中常見的緩存有兩種:
五,游戲日志
日志是個好東西呀,一個游戲中更不能少了日志,而且日志一定要記錄的詳細。它是玩家在整個游戲中的行為記錄,有了這個記錄,我們就可以分析玩家的行為,查找游戲的不足,在處理玩家在游戲中的問題時,日志也是一個良好的憑證和快速處理方式。
在游戲中,日志分為:
在構架設計中,日志記錄一定要做為一種強制行為,因為不強制的話,可能由于某種原因某個功能忘記加日志了,那么當這個功能出問題了,或者運營跟我們要這個功能的一些數據庫,就傻眼了。又得加需求,改代碼了。日志一定要設計一種良好的格式,日志記錄的數據要容易讀取,分解。日志行為可以用枚舉描述,在功能最后的處理方法里面加上這個枚舉做為參數,這樣不管誰在調用這個方法時,都要去加參數描述。
俗話說,工欲善其事,必先利其器。游戲管理工具是對游戲運行中的一系列問題處理的一種工具。它不僅是給開發(fā)人員用,大多數是給運營使用。游戲上線后,我們需要針對線上的問題進行不同的處理。不可能把所有問題都讓程序員去處理吧,于是程序員們想到了一個辦法,給你們做一個工具,你們愛誰處理誰處理去吧。
六, 游戲管理工具
游戲管理工具是一個不斷增漲的系統(tǒng),因為它很多時候是伴隨著游戲中遇到的問題而實現(xiàn)的。
但是根據經驗,有一些功能是必須有的,比如:
根據游戲的不同要求,凡是可以能過工具實現(xiàn)的,都做到游戲管理工具里面。它是針對所有服務器的管理。
一個好的,全的游戲管理工具,可以提高游戲運營中遇到問題處理的效率,為玩家提供更好的服務。
七,公共組件
公共組件是為游戲運行中提供公共的服務。例如:
這些都是針對所有區(qū)服提供的服務,所以要單獨做,與游戲邏輯分開,這樣方便管理,部署和負載均衡。
還有SDK的登陸驗證,現(xiàn)在手游比較多,與渠道對接里要進行驗證,這往往是很多http請求,速度慢,所以這個也要拿出來單獨做,不要在游戲邏輯中去驗證,因為網絡IO的訪問時間是不可控制的,http是阻塞的請求。
所以,綜上來看,一個游戲服務器起碼有幾個大的功能模塊組成:
根據游戲的不同需要,可能還有其它的。所在構架的設計中,一定要考慮到系統(tǒng)的分布式部署,盡量把公共的功能拆出來做,這樣可以增強系統(tǒng)的可擴展性。
服務器端開發(fā)的一些建議
本文作為游戲服務器端開發(fā)的基本大綱,是游戲實踐開發(fā)中的總結。
第一部分 —— 專業(yè)基礎,用于指導招聘和實習考核;
第二部分 —— 游戲入門,講述游戲服務器端開發(fā)的基本要點;
第三部分 —— 服務端架構,介紹架構設計中的一些基本原則。
希望能幫到大家!
一、專業(yè)基礎
1.1網絡
1.1.1理解TCP/IP協(xié)議
網絡傳輸模型
滑動窗口技術
建立連接的三次握手與斷開連接的四次握手
連接建立與斷開過程中的各種狀態(tài)
TCP/IP協(xié)議的傳輸效率
思考:
請解釋DOS攻擊與DRDOS攻擊的基本原理
一個100Byte數據包,精簡到50Byte, 其傳輸效率提高了50%
TIMEWAIT狀態(tài)怎么解釋?
1.1.2掌握常用的網絡通信模型
Select
Epoll,邊緣觸發(fā)與平臺出發(fā)點區(qū)別與應用
Select與Epoll的區(qū)別及應用
1.2存儲
1.3程序
二、游戲開發(fā)入門
2.1防御式編程
不要相信客戶端數據,一定要檢驗。作為服務器端你無法確定你的客戶端是誰,你也不能假定它是善意的,請做好自我保護。(這是判斷一個服務器端程序員是否入門的基本標準)
務必對于函數的傳人參數和返回值進行合法性判斷,內部子系統(tǒng),功能模塊之間不要太過信任,要求低耦合,高內聚。
插件式的模塊設計,模塊功能的健壯性應該是內建的,盡量減少模塊間耦合。
2.2設計模式
道法自然。不要迷信,迷戀設計模式,更不要生搬硬套
簡化,簡化,再簡化,用最簡單的辦法解決問題
借大寶一句話:設計本天成,妙手偶得之
2.3網絡模型
自造輪子: Select, Epoll, Epoll一定比Select高效嗎?
開源框架: Libevent, libev, ACE。
2.4數據持久化
2.5內存管理
2.6日志系統(tǒng)
2.7通信協(xié)議
2.8全局唯一Key(GUID)
2.9多線程與同步
2.10狀態(tài)機
2.11數據包操作
2.12狀態(tài)監(jiān)控
2.13包頻率控制
2.14開關控制
2.15反外掛反作弊
2.16熱更新
2.17防刷
2.18防崩潰
2.19性能優(yōu)化
2.20運營支持
2.21容災與故障預案
略
三、服務器端架構
3.1什么是好的架構?
3.2架構實踐的思考
游戲服務器的設計是一項頗有挑戰(zhàn)性的工作,游戲服務器的發(fā)展也由以前的單服結構轉變?yōu)槎喾C構,甚至出現(xiàn)了bigworld引擎的分布式解決方案,最近了解到Unreal的服務器解決方案atlas也是基于集群的方式。
負載均衡是一個很復雜的課題,這里暫不談bigworld和atlas的這類服務器的設計,更多的是基于功能和場景劃分服務器結構。
首先說一下思路,服務器劃分基于以下原則:
服務器結構圖:
各個服務器的簡要說明:
對服務器采用高吞吐量連接,如阻塞或異步IO。
網關主要有以下用途:
World Server 是一個控制中心,它負責把各種計算資源分布到各個服務器,它具有以下職責:
Phys Server 主要用于玩家移動,碰撞等檢測。
所有玩家的移動類操作都在該服務器上做檢查,所以該服務器本身具備所有地圖的地形等相關信息。具體檢查過程是這樣的:首先,Worldserver收到一個移動信息,WorldServer收到后向Phys Server請求檢查,Phys Server檢查成功后再返回給world Server,然后world server傳遞給相應的Scene Server。
Scene Server場景服務器,按場景劃分,每個服務器負責的場景應該是可以配置的。理想情況下是可以動態(tài)調節(jié)的。
ItemMgr Server 物品管理服務器,負責所有物品的生產過程。在該服務器上存儲一個物品掉落數據庫,服務器初始化的時候載入到內存。任何需要產生物品的服務器均與該服務器直接通信。
AIServer 又一個功能服務器,負責管理所有NPC的AI。AI服務器通常有2個輸入:
在這個設計中,對其他服務器來說,AIServer就是一個擁有很多個NPC的客戶端。AIserver需要同步所有與AI相關的數據,包括很多玩家數據。由于AIServer的Timer驅動特性,可在很大程度上使用TBB程序庫來發(fā)揮多核的性能。
把網絡游戲服務器分拆成多個進程,分開部署。
前些年,我也曾寫過好幾篇與之相關的設計。這幾天在思考一個問題:如果我們要做一個底層通用模塊,讓后續(xù)開發(fā)更為方便。到底要解決怎樣的需求?這個需求應該是單一且基礎的,每個應用都需要的。
正如 TCP 協(xié)議解決了互聯(lián)網上穩(wěn)定可靠的點對點數據流通訊一樣。游戲世界實際需要的是一個穩(wěn)定可靠的在游戲系統(tǒng)內的點對點通訊需要。
我們可以在一條 TCP 連接之上做到這一點。一旦實現(xiàn),可以給游戲服務的開發(fā)帶來極大的方便。
可以把游戲系統(tǒng)內的各項服務,包括并不限于登陸,拍賣,戰(zhàn)斗場景,數據服務,等等獨立服務看成網絡上的若干終端。每個玩家也可以是一個獨立終端。它們一起構成一個網絡。在這個網絡之上,終端之間可以進行可靠的連接和通訊。
實現(xiàn)可以是這樣的:
755800提供香港服務器、美國服務器等全球海外服務器租用托管,是區(qū)域鏈、直銷、流媒體、外貿、游戲等服務器解決方案首選品牌。755800已為多家企業(yè)提供區(qū)塊鏈服務器租用托管解決方案,為他們的區(qū)塊鏈安全提供支持!具體詳詢在線客服!
海外服務器免費測試:http://running-capacitor.com/