王盛林
(上海竹靈網(wǎng)絡(luò)科技有限公司 上海200120)
基于PHP的socket游戲服務(wù)器設(shè)計(jì)與實(shí)現(xiàn)
王盛林
(上海竹靈網(wǎng)絡(luò)科技有限公司 上海200120)
近年來(lái)網(wǎng)頁(yè)游戲、手機(jī)游戲快速發(fā)展,對(duì)游戲服務(wù)端提出新的要求:架構(gòu)簡(jiǎn)單、配置靈活,同時(shí)可支持快速開(kāi)發(fā)。文中提出一種架構(gòu):服務(wù)器底層通訊基于高性能的socket庫(kù)開(kāi)發(fā),而游戲邏輯采用成熟的PHP框架開(kāi)發(fā),游戲邏輯不關(guān)心底層細(xì)節(jié)達(dá)到快速高效的目的。文中主要分三層介紹:基礎(chǔ)層主要采用libevent和ZeroMQ的API;核心服務(wù)層提供網(wǎng)絡(luò)通訊和數(shù)據(jù)存儲(chǔ)服務(wù);應(yīng)用層處理游戲內(nèi)的邏輯。此外,以該架構(gòu)的游戲服務(wù)器已在兩款網(wǎng)頁(yè)游戲開(kāi)服上百組,性能測(cè)試穩(wěn)定。
游戲服務(wù)器;套接字;libevent;ZeroMQ;PHP
在游戲產(chǎn)業(yè)快速發(fā)展的今天,越來(lái)越多的公司因?yàn)橐豢钣螒蚓蛷幕ヂ?lián)網(wǎng)公司當(dāng)中脫穎而出,相比于傳統(tǒng)的MMORPG客戶(hù)端游戲,網(wǎng)頁(yè)游戲與手機(jī)游戲由于其便捷性更容易實(shí)際盈利目標(biāo)。因單服規(guī)模相對(duì)較小,游戲服務(wù)端無(wú)須復(fù)雜的服務(wù)器架構(gòu),需要能快速開(kāi)服,如何能保持在多人同時(shí)游戲時(shí)的流暢性以及系統(tǒng)的穩(wěn)定性是對(duì)游戲開(kāi)發(fā)人員的一大考驗(yàn)。由于這類(lèi)游戲要求開(kāi)發(fā)周期短、開(kāi)服速度快,因此需要綜合考慮成本與機(jī)動(dòng)性,同時(shí)又要求保證性能。文中就當(dāng)前比較熱門(mén)的網(wǎng)頁(yè)游戲和手機(jī)游戲,提出了一款基于PHP的Socket的游戲服務(wù)器,在底層引進(jìn) libevent庫(kù)提高負(fù)載能力和ZeroMQ庫(kù)來(lái)進(jìn)行服務(wù)器的通訊,游戲邏輯層采用PHP開(kāi)發(fā),最終達(dá)到快速與高效的目的。
1.1 基礎(chǔ)層分析
游戲服務(wù)器采用PHP作為腳本開(kāi)發(fā)語(yǔ)言,因其跨平臺(tái)、易布署、維護(hù)方便等特性,得到廣泛應(yīng)用。通過(guò)Socket網(wǎng)絡(luò)編程中成熟的技術(shù)方案來(lái)處理游戲中高連接數(shù)、高吞吐量的事件[1]。同時(shí)PHP支持C編寫(xiě)擴(kuò)展,可以做到與游戲服務(wù)器數(shù)據(jù)通訊一致。在底層采用類(lèi)庫(kù)有:
1)Libevent庫(kù),使用事件驅(qū)動(dòng)方式極大的降低資源占用,增大服務(wù)接待能力,并提高網(wǎng)絡(luò)傳輸效率。
2)ZeroMQ號(hào)稱(chēng)“史上最快的消息隊(duì)列”,他提供的API讓復(fù)雜的消息處理更加簡(jiǎn)潔同時(shí)性能更高。
1.2 底層庫(kù)libevent
libevent是一個(gè)開(kāi)源的事件觸發(fā)的網(wǎng)絡(luò)庫(kù),適用于windows、linux、bsd等多種平臺(tái),按不同平臺(tái)采用select、epoll、kqueue等系統(tǒng)調(diào)用管理事件機(jī)制。對(duì)于每個(gè)網(wǎng)絡(luò)請(qǐng)求,libevent相當(dāng)于在各個(gè)平臺(tái)的網(wǎng)絡(luò)后端增加一個(gè)包裝器,讓事件管理在得以最高效最高性能,同時(shí)事件系統(tǒng)優(yōu)化讓處理函數(shù)非常方便,有效降低底層I/O復(fù)雜性。其主要功能有:
1)采用事件驅(qū)動(dòng)機(jī)制,異步調(diào)用性能高。
2)專(zhuān)注于網(wǎng)絡(luò)處理,方便編寫(xiě)。
3)跨平臺(tái)支持,嘗試使用每個(gè)平臺(tái)上最高速的非阻塞IO實(shí)現(xiàn),并且不引入太多的額外開(kāi)銷(xiāo)。
4)支持I/O(socket)、定時(shí)器和信號(hào)事件。
5)支持多種I/O多路復(fù)用技術(shù),有效提高網(wǎng)絡(luò)傳輸效率。
6)其他組件提供緩沖的事件系統(tǒng),以及HTTP、DNS和RPC系統(tǒng)核心實(shí)現(xiàn)。
libevent在網(wǎng)絡(luò)編程得到充分驗(yàn)證,采用基于libevent為底層的成熟服務(wù)器端:Memcache(分布式緩存)[2],PLB(負(fù)載均衡器),而對(duì)PHP支持很好的有Swoole[3]、ReactPHP[4]等。
1.3 底層庫(kù)ZeroMQ
ZeroMQ[5]是消息隊(duì)列管理庫(kù),其提供底層的網(wǎng)絡(luò)通訊庫(kù),對(duì)Socket API做了一層封裝,將網(wǎng)絡(luò)通訊、進(jìn)程通訊和線(xiàn)程通訊作為統(tǒng)一的API接口,其主要優(yōu)點(diǎn)有:
1)支持高并發(fā)、異步調(diào)用,速度快。
2)支持多個(gè)消息傳送模式:如P2P、訂閱發(fā)布模式、以及請(qǐng)求響應(yīng)模式。
3)支持多個(gè)平臺(tái):如Linux/Windows/OSX等。
4)協(xié)議比 TCP更快、適用于大型集群和分布式計(jì)算
5)開(kāi)源社區(qū)支持,支持多種開(kāi)發(fā)語(yǔ)言。
圖1 游戲服務(wù)器端結(jié)構(gòu)示意圖
傳統(tǒng)客戶(hù)端服務(wù)器在線(xiàn)人數(shù)多,游戲邏輯復(fù)雜,所以已發(fā)展出成熟的解決方案:如魔獸世界(WOW)采用的BigWorld[6]方案,功能強(qiáng)大,動(dòng)態(tài)負(fù)載均衡和容錯(cuò)性做了很多工作,但同時(shí)硬件要求比較高,價(jià)格昂貴。它的服務(wù)器端架構(gòu)分為Gate(網(wǎng)關(guān)服務(wù)器,負(fù)責(zé)客戶(hù)端連接及消息轉(zhuǎn)發(fā))、GameServer(提供游戲邏輯功能的服務(wù)器程序)、DBManager(負(fù)責(zé)將游戲數(shù)據(jù)寫(xiě)入到數(shù)據(jù)庫(kù))、GameManager(處理所有GameServer中消息處理)。
文中主要借鑒這種架構(gòu)思路:按數(shù)據(jù)通訊服務(wù)、數(shù)據(jù)存儲(chǔ)服務(wù)、定時(shí)器服務(wù)、消息服務(wù)劃分,可實(shí)現(xiàn)一臺(tái)獨(dú)立物理服務(wù)器提供所有核心服務(wù),或者一個(gè)服務(wù)提供給多臺(tái)服務(wù)器,同時(shí)還支持分布式服務(wù),按照實(shí)際開(kāi)服情況靈活處理,實(shí)現(xiàn)快速機(jī)動(dòng)、節(jié)約成本。
2.1 數(shù)據(jù)通訊服務(wù)
2.1.1 功能說(shuō)明
數(shù)據(jù)通訊服務(wù)類(lèi)似Gateway網(wǎng)關(guān)服務(wù)器,負(fù)責(zé)網(wǎng)絡(luò)數(shù)據(jù)的接收與發(fā)送,將客戶(hù)端發(fā)送的數(shù)據(jù)解碼后發(fā)送游戲邏輯層處理,對(duì)游戲邏輯發(fā)過(guò)來(lái)的數(shù)據(jù)編碼后發(fā)送給客戶(hù)端。由于在線(xiàn)玩家通過(guò)TCP直接連到服務(wù)器,所以承載很大的壓力,數(shù)據(jù)通訊服務(wù)具有如下特點(diǎn):
1)響應(yīng)時(shí)間及時(shí):與游戲客戶(hù)端一樣,響應(yīng)越快游戲越流暢,延時(shí)過(guò)長(zhǎng)會(huì)大大降低游戲體檢。
2)服務(wù)可擴(kuò)展:根據(jù)游戲人數(shù)確定增加負(fù)載能力,如增加Worker進(jìn)程,多開(kāi)通訊進(jìn)程等。
3)服務(wù)穩(wěn)定性:游戲是7*24不間斷服務(wù),所以需要提供由于在線(xiàn)人數(shù)多或者少各種情況下的應(yīng)用平穩(wěn)以及各種異常的修復(fù)及處理功能。
2.1.2 方案說(shuō)明
游戲服務(wù)是網(wǎng)絡(luò)IO密集型服務(wù),采用方案是:
1)采用libevent庫(kù)作為網(wǎng)絡(luò)通訊接口:由于libevent采用事件驅(qū)動(dòng)模式,非阻塞網(wǎng)絡(luò)IO,采用EPOLL事件輪循機(jī)制,盡管采用多進(jìn)程,但由于游戲邏輯執(zhí)行優(yōu)化后,并行處理數(shù)據(jù)輸入輸出還是很高效的。通訊服務(wù)以常駐進(jìn)程方式啟動(dòng),worker進(jìn)程收到客戶(hù)端發(fā)來(lái)的請(qǐng)求,以C加載CLI的方式執(zhí)行PHP業(yè)務(wù)邏輯,處理結(jié)果PHP通知給worker,中間用C編寫(xiě)的PHP擴(kuò)展保持?jǐn)?shù)據(jù)結(jié)構(gòu)一致。
2)服務(wù)端采用Master-Workers結(jié)構(gòu) (管理者-工作者):這種結(jié)構(gòu)能夠動(dòng)態(tài)管理游戲服務(wù)進(jìn)程,從而提高處理效率。如:Nginx[6]、PHP-FPM[7]都采用這種方式。主要特點(diǎn)有:
①多進(jìn)程由操作系統(tǒng)來(lái)調(diào)度,管理方便,運(yùn)行起來(lái)比較強(qiáng)壯穩(wěn)定。
②隔離性好,可由Master來(lái)管理worker進(jìn)程,實(shí)現(xiàn)平滑的加載游戲配置以達(dá)熱更新。
③充分利用多核cpu來(lái)進(jìn)行并行運(yùn)算,利用率高。具體工作示意圖如圖2。
圖2 通訊服務(wù)結(jié)構(gòu)示意圖
2.2 定時(shí)器服務(wù)
定時(shí)器服務(wù)是以加載配置的方式,執(zhí)行應(yīng)用層的業(yè)務(wù)邏輯。可直接使用其來(lái)創(chuàng)建定時(shí)啟動(dòng)、關(guān)閉應(yīng)用。設(shè)定時(shí)間到來(lái)時(shí),會(huì)自動(dòng)執(zhí)行配置中指定應(yīng)用層游戲邏輯。一般用在游戲活動(dòng)開(kāi)啟、關(guān)閉,定時(shí)恢復(fù)游戲?qū)傩缘取?/p>
其中游戲中一些需要異步去處理的應(yīng)用,以常駐進(jìn)程方式加載,也用定時(shí)器來(lái)實(shí)現(xiàn)。如一些比較占用網(wǎng)絡(luò)IO資源、業(yè)務(wù)邏輯復(fù)雜的服務(wù):合作商之間的充值驗(yàn)證服務(wù)、游戲戰(zhàn)斗結(jié)算服務(wù)等,以隊(duì)列形式處理請(qǐng)求,有效平衡服務(wù)器負(fù)載。
2.3 數(shù)據(jù)存儲(chǔ)服務(wù)
游戲中玩家數(shù)據(jù)分成兩種方式存儲(chǔ):一種存儲(chǔ)在物理介質(zhì)上的DataBase(如一般的關(guān)系型數(shù)據(jù)庫(kù),MySQL/SQLServer等)中,另一種存儲(chǔ)在內(nèi)存為介質(zhì)的NoSQL中 (如Redis、Mongo等)??紤]到游戲的高性能需要,對(duì)于實(shí)時(shí)操作的數(shù)據(jù)放在以?xún)?nèi)存為介質(zhì)的NoSQL中,而那些需要提供給數(shù)據(jù)分析的數(shù)據(jù)會(huì)寫(xiě)入數(shù)據(jù)庫(kù)中。
2.3.1 關(guān)系型數(shù)據(jù)庫(kù)DataBase
關(guān)系型數(shù)據(jù)庫(kù)是創(chuàng)建在關(guān)系模型(relational database)基礎(chǔ)上的數(shù)據(jù)庫(kù),借助于集合代數(shù)等概念和方法來(lái)處理數(shù)據(jù)庫(kù)中的數(shù)據(jù)。由于游戲中操作頻繁,磁盤(pán)IO成了性能瓶頸,主要用于玩家游戲數(shù)據(jù)的持久化:如保留一些用戶(hù)信息以及游戲日志。
2.3.2 內(nèi)存型數(shù)據(jù)庫(kù)NoSQL
NoSQL不同于傳統(tǒng)的關(guān)系型數(shù)據(jù)庫(kù),已經(jīng)不使用SQL作為查詢(xún)語(yǔ)言。NoSQL數(shù)據(jù)庫(kù)有幾大好處:大數(shù)據(jù)量,高性能,支持集群,易部署。本例采用的Redis[8]是一種key-value對(duì)應(yīng)結(jié)構(gòu)的內(nèi)存數(shù)據(jù)庫(kù),存儲(chǔ)效率高。同時(shí)支持定時(shí)器、自動(dòng)排序結(jié)構(gòu)(stored set)、邏輯事務(wù)等結(jié)構(gòu),適合游戲內(nèi)的邏輯。還利用其提供的持久化用作游戲數(shù)據(jù)的備份。
2.4 消息通知服務(wù)
游戲邏輯需要在服務(wù)之間以及服務(wù)器組之間傳遞消息。文中采用的是ZeroMQ,其除了簡(jiǎn)潔快速外,對(duì)其中組件的啟動(dòng)順序沒(méi)有要求,適合游戲服務(wù)器動(dòng)態(tài)擴(kuò)展。文中使用ZeroMQ主要用到他的通訊模式只有兩類(lèi)。
1)請(qǐng)求回應(yīng)模型(Request-Reply)。
該模型為請(qǐng)求端(REQ)發(fā)起請(qǐng)求,等待回應(yīng)端(REP)回應(yīng)。因REQ端均只能在單線(xiàn)程中運(yùn)行,因此必須要recv與send配對(duì)使用,但利用支持的路由功能(Router),加大了REQ端的擴(kuò)展性,如下圖3,在游戲服務(wù)器常見(jiàn)情景如:客戶(hù)端發(fā)起戰(zhàn)斗請(qǐng)求,服務(wù)端將復(fù)雜的運(yùn)算結(jié)果返回給客戶(hù)端。
圖3 ZeroMQ的請(qǐng)求回應(yīng)模型
2)發(fā)布訂閱模型(Publish-Subscribe)。
訂閱端一旦連接上發(fā)布端就能收到發(fā)布端發(fā)送的消息,而沒(méi)連接上不影響發(fā)布端發(fā)布給其他訂閱端。同時(shí)如果發(fā)布端丟失,所有訂閱端都會(huì)等待發(fā)布端連接上直至發(fā)布新的消息,如下圖4所示。而對(duì)于訂閱端斷線(xiàn)重連消息丟失以及訂閱端后連接上而丟失消息均可有相應(yīng)解決方案。在游戲中實(shí)際常用在跨區(qū)玩法:不同游戲區(qū)組成一個(gè)跨區(qū)讓玩家玩一個(gè)模塊,跨區(qū)服相當(dāng)于發(fā)布端,其他游戲大區(qū)相當(dāng)于訂閱者,從而實(shí)現(xiàn)跨區(qū)消息傳送目的。
圖4 ZeroMQ的發(fā)布訂閱模型
應(yīng)用層采用PHP開(kāi)發(fā),開(kāi)發(fā)效率高,適合于頁(yè)游、手游這類(lèi)快速開(kāi)服平臺(tái)。采用高性能框架,采用內(nèi)存化數(shù)據(jù)緩存,能保證游戲邏輯快速響應(yīng)。
3.1 開(kāi)發(fā)框架
采用Yaf(Yet Another Framework)是由PHP核心開(kāi)發(fā)組成員惠新宸開(kāi)發(fā)一款用C語(yǔ)言擴(kuò)展開(kāi)源框,與其他框架CI、Zend Framework,Yii相比效率更高,無(wú)需編譯,在PHP啟動(dòng)時(shí)加載,并常駐內(nèi)存。優(yōu)化如圖5。
圖5 優(yōu)化框架圖
同時(shí)支持MVC(Model-View-Controller,應(yīng)用邏輯和表現(xiàn)邏輯分開(kāi))。游戲處理請(qǐng)求與發(fā)送請(qǐng)求代碼如下例:
3.2 加密與安全
由于PHP是一種腳本型語(yǔ)言,以明文方式保存在服務(wù)器,所以并不安全??梢圆捎肸end Guard Loader、ioncube等商業(yè)軟件來(lái)加密源代碼。
3.3 優(yōu)化與加速
由于PHP預(yù)編譯時(shí)會(huì)把源碼編成opcode緩存來(lái)達(dá)到加速目的,這里開(kāi)啟PHP5.5以后自帶OPCache[11],相對(duì)比eacce lerator、xcache、apc等緩存工具更穩(wěn)定。
對(duì)于游戲邏輯中用到的大量配置文件,采用緩存到redis方法達(dá)到加速目的。
3.4 模塊說(shuō)明
3.4.1 游戲邏輯模塊
采用MVC開(kāi)發(fā)模式,Models模型文件提供接口給Controller來(lái)處理游戲邏輯。
3.4.2 登陸模塊
由于目前手機(jī)游戲和網(wǎng)頁(yè)游戲大多聯(lián)合運(yùn)營(yíng),登陸、充值模塊都是以接口的方式與運(yùn)營(yíng)平臺(tái)通訊,所以這里采用WEB方式與平臺(tái)對(duì)接,與平臺(tái)驗(yàn)證成功便可進(jìn)入游戲邏輯。采用訪(fǎng)問(wèn)白名單方式來(lái)保證通訊安全,同時(shí)寫(xiě)入登陸日志以備查詢(xún)。
3.4.3 充值模塊
游戲開(kāi)發(fā)商提供充值接口與運(yùn)營(yíng)平臺(tái)充值平臺(tái)對(duì)接,來(lái)完成游戲內(nèi)充值。在游戲內(nèi)需要一個(gè)常駐進(jìn)程來(lái)處理來(lái)自運(yùn)營(yíng)平臺(tái)的充值邏輯。同樣這個(gè)接口需要設(shè)置白名單來(lái)保證安全性。由于充值會(huì)涉及很多游戲邏輯,所以這里將以隊(duì)列形式(如:Redis的List數(shù)據(jù)類(lèi)型)來(lái)處理。
3.4.4 日志模塊
1)一般游戲日志:如用戶(hù)消費(fèi)日志,使用日志一般均是在游戲邏輯中以數(shù)據(jù)庫(kù)形式保存,方便查詢(xún)和制作數(shù)據(jù)報(bào)表
2)游戲運(yùn)行日志:包括游戲邏輯異常、worker進(jìn)程異常日志,一般以文本形式保存,方便改進(jìn)。
在游戲行業(yè)快速發(fā)展的今天,技術(shù)變化日新月異,不斷有更優(yōu)化、更適合的方案出現(xiàn)?;赑HP的socket游戲服務(wù)器方案優(yōu)點(diǎn)明顯,但也有一些缺點(diǎn)。若是計(jì)算密集型應(yīng)用,就無(wú)法體現(xiàn)出libevent提供的異步非阻塞IO的優(yōu)點(diǎn)。本文從基礎(chǔ)層、核心層以及應(yīng)用層三部分進(jìn)行系統(tǒng)的介紹,實(shí)現(xiàn)一種快速高效的解決方案。通過(guò)對(duì)實(shí)際游戲運(yùn)行測(cè)試,結(jié)果表明該服務(wù)器可實(shí)現(xiàn)較高的穩(wěn)定性和運(yùn)行速度,達(dá)到所需目的。
[1](美)Pieter Hintjens.ZeroMQ:云時(shí)代極速消息通信庫(kù)[M].盧濤,李穎譯.北京:電子工業(yè)出版社,2015.
[2]李子婷.基于分布式中間件的多人在線(xiàn)網(wǎng)絡(luò)游戲的構(gòu)建[D].上海:復(fù)旦大學(xué),2010.
[3]陳俊,黃維平.分布式Memcached在社交游戲中的應(yīng)用研究[J].電腦知識(shí)與技術(shù),2011,7(10):2301-2305.
[4]Kjetil Raaen,Hard Espeland&HonKvale Stensland.ADemonstration Of aLoekless,Relaxed Atomicity State Parallel Game Server[D].NorwaySimulaResearchLaboratory,2010.
[5](美)Pieter Hintjens.ZeroMQ:云時(shí)代極速消息通信庫(kù)[M].盧濤,李穎譯.北京:電子工業(yè)出版社,2015.
[6]深入理解Nginx[M].陶輝.北京:機(jī)械工業(yè)出版社,2013.
[7](美)W.Richard Stevens,(美)BillFenner,(美)Andrew M.Rudoff.Tudoff.UNIX網(wǎng)絡(luò)編程卷1:套接字聯(lián)網(wǎng)API[M].3版.北京:人民郵電出版社,2010.
[8]Redis設(shè)計(jì)與實(shí)現(xiàn)[M].黃健宏.北京:機(jī)械工業(yè)出版社,2014.
The architectures of socket game server based on PHP
WANG Sheng-lin
(Shanghai Zhulin Network Inc.PostCode,Shanghai200120,China)
Web games,mobile games fast development today,the game server need simplearchitectures,flexible configuationandsupport high-efficiencydevelopment.This paper presents the design of Socket server-based game,usehighefficiency PHP framework to develop the game logic,and game logicdon't need to care about the server communication details.This papermainly describes the system in three parts from the base layer and core layer and application layer.Among them,the base layer ismainly done to pave the way for the subsequent development of pre-module,which consists of data,protocolmodules;the core layer provide data communication and data storage;application layer is the base layer on the base,by calling each module server package and handling agreements.In order to improve server performance and speed,at the application layer adds libevent and ZeroMQ two open source model.In this paper,the proposed technology for the server based on the developmentofa good stability and speed.
gameserver;Socket;libevent;ZeroMQ
TM933.4
A
1674-6236(2016)20-0125-04
2015-10-28 稿件編號(hào):201510208
王盛林(1977—),男,湖北蘄春人,工程師。研究方向:網(wǎng)頁(yè)游戲移動(dòng)游戲系統(tǒng)架構(gòu)與開(kāi)發(fā)。