發(fā)布時(shí)間:2023-11-29 16:05:07 瀏覽量:103次
隨著游戲市場(chǎng)的興起,特別是網(wǎng)頁(yè)游戲、手機(jī)游戲的崛起,對(duì)游戲開(kāi)發(fā)技術(shù)的需求越來(lái)越多。網(wǎng)絡(luò)游戲開(kāi)發(fā)是一個(gè)龐大的體系,總體來(lái)說(shuō)是客戶(hù)端與服務(wù)器端??蛻?hù)端是玩家接觸的游戲圖像顯示端,服務(wù)器是處理游戲運(yùn)行中的各種數(shù)據(jù),由于一臺(tái)服務(wù)器要支持眾多玩家的請(qǐng)求,所以服務(wù)器的性能高低決定了同一個(gè)游戲的用戶(hù)數(shù)量。
我們公司選擇使用Java做服務(wù)器開(kāi)發(fā)語(yǔ)言,主要原因是:1.Java是跨平臺(tái)的,方便部署;2.Java是安全的高級(jí)語(yǔ)言,可以提高開(kāi)發(fā)效率;3.Java是面向?qū)ο蟮模a可以重用;4.Java的分布式應(yīng)用。
圖1 服務(wù)器架構(gòu)圖
服務(wù)器架構(gòu)
Java在我們的服務(wù)器開(kāi)發(fā)中的應(yīng)用。服務(wù)器架構(gòu)如圖1所示。服務(wù)器架構(gòu)的幾個(gè)模塊:
這些模塊都是分開(kāi)的,可以靈活地分布式部署到不同的物理服務(wù)器上。只需要修改一些配置文件即可,非常方便。
服務(wù)器詳細(xì)功能模塊
登錄服務(wù)器
負(fù)責(zé)處理玩家登錄的請(qǐng)求。一個(gè)登錄服務(wù)器對(duì)應(yīng)多個(gè)游戲邏輯分區(qū)。當(dāng)玩家登錄的時(shí)候,登錄服務(wù)器向用戶(hù)中心服務(wù)器發(fā)送登錄信息。請(qǐng)求對(duì)登錄信息的驗(yàn)證。通過(guò)驗(yàn)證之后,返回分區(qū)地址,之后,客戶(hù)端與登錄服務(wù)器斷開(kāi),連接到游戲邏輯服務(wù)器。登錄服務(wù)器是一個(gè)單獨(dú)的Java運(yùn)行程序,當(dāng)訪(fǎng)問(wèn)量增加大,可以增加部署到多個(gè)物理服務(wù)器上面,均衡負(fù)載訪(fǎng)問(wèn)壓力。它通過(guò)使用Java的NIO(非阻塞)方式與客戶(hù)端進(jìn)行通信。通過(guò)用戶(hù)中心服務(wù)器提供的接口訪(fǎng)問(wèn)用戶(hù)中心,進(jìn)行數(shù)據(jù)處理。
邏輯服務(wù)器
對(duì)玩家的操作進(jìn)行邏輯處理。邏輯服務(wù)器是整個(gè)游戲的心臟。它的工作效率直接影響玩家在游戲中的體驗(yàn),所以對(duì)它的要求就是速度,快速返回處理結(jié)果。為了達(dá)到滿(mǎn)足要求的速度,邏輯服務(wù)器的大部分操作必須在內(nèi)存中操作,避免I/O操作,I/O操作可以放到另外的線(xiàn)程中進(jìn)行。說(shuō)是大部分,是因?yàn)橥婕以诘谝淮蔚卿浀臅r(shí)候可能會(huì)從數(shù)據(jù)庫(kù)加載所要用到的數(shù)據(jù)。在圖中,大家看到了緩存,緩存的作用就是把數(shù)據(jù)放在內(nèi)存中。當(dāng)玩家退出時(shí),它的數(shù)據(jù)也會(huì)在緩存中保存一段時(shí)間,在一定時(shí)間內(nèi),玩家再次登錄,將不會(huì)再重新從數(shù)據(jù)庫(kù)加載數(shù)據(jù)。在邏輯服務(wù)器中對(duì)數(shù)據(jù)庫(kù)的操作可以先放入一個(gè)Java隊(duì)列中,再另起一個(gè)Java線(xiàn)程負(fù)責(zé)從這個(gè)隊(duì)列取數(shù)據(jù),并發(fā)送到數(shù)據(jù)庫(kù)服務(wù)器,這就是使用Java的阻塞隊(duì)列,快速實(shí)現(xiàn)一個(gè)生產(chǎn)者—消費(fèi)者模式,數(shù)據(jù)生產(chǎn)與處理相分離,這樣既減輕了邏輯服務(wù)器的壓力,也保證了數(shù)據(jù)處理的效率。邏輯服務(wù)器的日志也不在邏輯服務(wù)器入庫(kù),同樣的發(fā)送到日志服務(wù)器處理。還有一種方法是以一種特定格式的方式,記錄到本地文件中,再啟動(dòng)一個(gè)進(jìn)程,讀取這個(gè)文件,然后入庫(kù)。
用戶(hù)中心服務(wù)器
現(xiàn)在很多游戲都對(duì)用戶(hù)進(jìn)行了集中管理。這方便了對(duì)用戶(hù)提供更好的服務(wù),比如充值、活動(dòng)、禮包領(lǐng)取、新游戲?qū)胗脩?hù)等。有的游戲公司可能會(huì)用用戶(hù)中心的數(shù)據(jù)發(fā)展游戲運(yùn)營(yíng)平臺(tái)。這部分與游戲邏輯服務(wù)器分開(kāi),也減少了游戲邏輯服務(wù)器的壓力。用戶(hù)中心采用JavaWeb開(kāi)發(fā),它對(duì)游戲服務(wù)器只提供特定訪(fǎng)問(wèn)的接口,把數(shù)據(jù)與邏輯分離開(kāi)來(lái),方便管理,以及分布式部署,增強(qiáng)了架構(gòu)的靈活性。
充值服務(wù)器
充值是游戲收入的唯一方式,所以這個(gè)功能必須流暢,毫無(wú)壓力。如果由于網(wǎng)絡(luò)或服務(wù)器性能原因,導(dǎo)致玩家充值不了,會(huì)直接影響收益的。所以充值服務(wù)器最好部署在一臺(tái)單獨(dú)的物理機(jī)上面,也可以多個(gè)分區(qū)使用一個(gè)充值服務(wù)器,這要視游戲人數(shù)而定。
數(shù)據(jù)庫(kù)服務(wù)器
負(fù)責(zé)對(duì)數(shù)據(jù)入庫(kù)及更新的操作。把這部分操作從邏輯服務(wù)器分離出來(lái),就是為了減輕邏輯服務(wù)器的壓力,減少邏輯服務(wù)器資源的占用。而且,如果邏輯服務(wù)器突然宕機(jī)的話(huà),也能盡量保證數(shù)據(jù)少丟失。為了保證對(duì)數(shù)據(jù)的更新是順序性的,這里把數(shù)據(jù)入庫(kù)的操作使用隊(duì)列單線(xiàn)程化。邏輯服務(wù)器與數(shù)據(jù)庫(kù)服務(wù)器通過(guò)Java的TCP/IPSocket進(jìn)行長(zhǎng)連接,而且為了防止由于意外原因?qū)е逻B接中斷,在邏輯服務(wù)器與數(shù)據(jù)庫(kù)服務(wù)器之間加入了一個(gè)心跳連接,這樣短暫的中斷可以被很快恢復(fù),防止數(shù)據(jù)的丟失。
日志服務(wù)器
處理玩家日志的入庫(kù)。日志入庫(kù)方便游戲運(yùn)營(yíng)管理游戲,統(tǒng)計(jì)玩家信息。當(dāng)玩家人數(shù)比較多的時(shí)候,日志也會(huì)占用很多資源。所以把日志從邏輯服務(wù)器也分開(kāi)了,因?yàn)槿罩局皇遣迦氩僮?,所以可以開(kāi)幾個(gè)線(xiàn)程進(jìn)行并發(fā)插入到數(shù)據(jù)庫(kù)。線(xiàn)程數(shù)要根據(jù)你數(shù)據(jù)庫(kù)的連接池的最大連接數(shù)進(jìn)行設(shè)置,要不然會(huì)導(dǎo)致連接資源被占完,數(shù)據(jù)插入不了數(shù)據(jù)庫(kù)。
注意事項(xiàng)
在游戲服務(wù)器開(kāi)發(fā)中,有幾個(gè)需要注意的問(wèn)題。
通信協(xié)議
開(kāi)始的時(shí)候,我們?yōu)榱丝焖匍_(kāi)發(fā),采用了JSON的變長(zhǎng)協(xié)議處理方式,即把要傳送的數(shù)據(jù)編碼成json的字符串,再把json字符串轉(zhuǎn)化為字節(jié)數(shù)據(jù),傳輸過(guò)程中包的總結(jié)構(gòu)為:總包長(zhǎng)度(int四個(gè)字節(jié))+消息長(zhǎng)度(int四個(gè)字節(jié))+消息體,即數(shù)據(jù)長(zhǎng)度,n個(gè)字節(jié)。這樣做的好處是可以快速開(kāi)發(fā),缺點(diǎn)是在傳輸過(guò)程中無(wú)效的字節(jié)太多。而且這部分完全可以用代碼自動(dòng)完成。后來(lái)我們采用Java的反射機(jī)制,從定義好的xml描述協(xié)議文件中讀取傳輸?shù)膬?nèi)容格式,自動(dòng)化生成傳輸?shù)膶?duì)象,在發(fā)送信息時(shí),根據(jù)這個(gè)對(duì)象再把數(shù)據(jù)轉(zhuǎn)化為二進(jìn)制的數(shù)據(jù)流,解析的時(shí)候,同樣也根據(jù)xml的描述文件,按順序讀取數(shù)據(jù)并轉(zhuǎn)化為對(duì)象的JavaBean對(duì)象。如果時(shí)間充足,在游戲開(kāi)發(fā)前期應(yīng)該把這個(gè)做好。
多線(xiàn)程并發(fā)
游戲服務(wù)器是一個(gè)多用戶(hù)的環(huán)境,其中多線(xiàn)程是必不可少的,它可以提交程序?qū)PU的利用率,提高處理性能。但它也有一個(gè)致命的缺點(diǎn),就是在多線(xiàn)程下,數(shù)據(jù)同步的問(wèn)題。因?yàn)樵谀壳岸嗪薈PU下,線(xiàn)程算得上是可以并行執(zhí)行的了。比如競(jìng)技場(chǎng)中的排行榜,每個(gè)玩家的名次變化都會(huì)對(duì)排行榜進(jìn)行操作。如果不考慮數(shù)據(jù)同步的話(huà),每個(gè)玩家可以隨意更新排行榜,那這個(gè)排行榜的數(shù)據(jù)就會(huì)非常亂,名次也不正確。這個(gè)時(shí)間就需要保證在一個(gè)玩家更新排行的時(shí)候,其他玩家不能更新,只能阻塞等待。一般有兩種方法可以解決:1.直接使用鎖,當(dāng)一個(gè)玩家更新排行榜時(shí),使用鎖鎖定排行榜集合,讓其他玩家不能再對(duì)排行榜操作,Java有自帶的兩種方式,非常方便,一個(gè)是Lock接口,一個(gè)是Synchronized;2.使用樂(lè)觀(guān)同步,這種方式需要自己額外實(shí)現(xiàn),之所以說(shuō)是樂(lè)觀(guān),是因?yàn)樗锌赡軋?zhí)行失敗。原理是當(dāng)我取數(shù)據(jù)時(shí),獲得一個(gè)數(shù)據(jù)的一個(gè)版本號(hào),而當(dāng)寫(xiě)入數(shù)據(jù)時(shí),如果版本一致,可寫(xiě)入,如果版本不一致,就需要重新獲取數(shù)據(jù),執(zhí)行邏輯,直到版本一致后寫(xiě)入。可以設(shè)定重復(fù)次數(shù),達(dá)到這個(gè)次數(shù)后,還沒(méi)有成功就判定失敗。根據(jù)我們目前的運(yùn)行環(huán)境,我們采用了第一種方式。
均衡負(fù)載
一臺(tái)物理服務(wù)器的處理能力是有限的,對(duì)于可能支持?jǐn)?shù)據(jù)眾多的游戲服務(wù)器來(lái)說(shuō),分布式部署和動(dòng)態(tài)添加服務(wù)器是不可缺少的。在邏輯上,可以把需要集中處理,與邏輯運(yùn)算關(guān)系不大的模塊單獨(dú)部署。比如登錄服務(wù)器、地圖服務(wù)器、聊天服務(wù)器、數(shù)據(jù)庫(kù)服務(wù)器等。像我們把登錄服務(wù)器和數(shù)據(jù)庫(kù)服務(wù)器分離開(kāi)就是為了減少邏輯服務(wù)器的壓力。
緩存的設(shè)計(jì)
起初,為了快速敏捷開(kāi)發(fā),我們采用了一級(jí)緩存方式,即圖1中的Redis緩存,它是一個(gè)分布式的緩存,內(nèi)部通過(guò)Socket連接。在玩家第一次進(jìn)入游戲的時(shí)候會(huì)把玩家數(shù)據(jù)從數(shù)據(jù)庫(kù)加載到Redis緩存之中,再取數(shù)據(jù)只從緩存中取。后來(lái)為了更加提高處理速度,增加了二級(jí)緩存,即內(nèi)存緩存,利用Java提供的Map、List等集合保存數(shù)據(jù),開(kāi)發(fā)了一個(gè)基于內(nèi)存的緩存構(gòu)架MemoryCacheTool,對(duì)外只提供操作接口。由于是直接從內(nèi)存中讀取或?qū)懭霐?shù)據(jù),其速度相對(duì)于Redis提高大約20%左右。
總結(jié)
Java是一門(mén)安全、高效、跨平臺(tái)的語(yǔ)言,它在游戲服務(wù)器開(kāi)發(fā)過(guò)程中可以提高開(kāi)發(fā)效率,減少異常,增強(qiáng)程序的健壯性。它很容易實(shí)現(xiàn)各個(gè)功能的銜接,方便后期的維護(hù)。
王廣帥
作者簡(jiǎn)介:王廣帥,網(wǎng)名wgslucky,2011年畢業(yè)開(kāi)始參加工作,一直從事于游戲服務(wù)器的開(kāi)發(fā)工作。現(xiàn)任北京觸云科技有限公司服務(wù)器端技術(shù)主程,是一名技術(shù)狂,熱愛(ài)讀書(shū),喜歡挑戰(zhàn),熱衷與技術(shù)同道分享交流游戲開(kāi)發(fā)方面的技術(shù)。
本文選自程序員電子版2015年5月B刊,該期更多文章請(qǐng)查看這里。2000年創(chuàng)刊至今所有文章目錄請(qǐng)查看程序員封面秀。歡迎訂閱程序員電子版(含iPad版、Android版、PDF版)。
熱門(mén)資訊
探討游戲引擎的文章,介紹了10款游戲引擎及其代表作品,涵蓋了RAGE Engine、Naughty Dog Game Engine、The Dead Engine、Cry Engine、Avalanche Engine、Anvil Engine、IW Engine、Frostbite Engine、Creation引擎、Unreal Engine等引擎。借此分析引出了游戲設(shè)計(jì)領(lǐng)域和數(shù)字藝術(shù)教育的重要性,歡迎點(diǎn)擊咨詢(xún)報(bào)名。
2. 手機(jī)游戲如何開(kāi)發(fā)(如何制作傳奇手游,都需要準(zhǔn)備些什么?)
?如何制作傳奇手游,都需要準(zhǔn)備些什么?提到傳奇手游相信大家都不陌生,他是許多80、90后的回憶;從起初的端游到現(xiàn)在的手游,說(shuō)明時(shí)代在進(jìn)步游戲在更新,更趨于方便化移動(dòng)化。而如果我們想要制作一款傳奇手游的
3. B站視頻剪輯軟件「必剪」:免費(fèi)、炫酷特效,小白必備工具
B站視頻剪輯軟件「必剪」,完全免費(fèi)、一鍵制作炫酷特效,適合新手小白??靵?lái)試試!
4. Steam值得入手的武俠游戲盤(pán)點(diǎn),各具特色的快意江湖
游戲中玩家將面臨武俠人生的掙扎抉擇,戰(zhàn)或降?殺或放?每個(gè)抉定都將觸發(fā)更多愛(ài)恨糾葛的精彩奇遇?!短烀嬗肪哂卸嗑€(xiàn)劇情多結(jié)局,不限主線(xiàn)發(fā)展,高自由...
5. Bigtime加密游戲經(jīng)濟(jì)體系揭秘,不同玩家角色的經(jīng)濟(jì)活動(dòng)
Bigtime加密游戲經(jīng)濟(jì)模型分析,探討游戲經(jīng)濟(jì)特點(diǎn),幫助玩家更全面了解這款GameFi產(chǎn)品。
6. 3D動(dòng)漫建模全過(guò)程,不是一般人能學(xué)的會(huì)的,會(huì)的多不是人?
步驟01:面部,頸部,身體在一起這次我不準(zhǔn)備設(shè)計(jì)圖片,我從雕刻進(jìn)入。這一次,它將是一種純粹關(guān)注建模而非整體繪畫(huà)的形式。像往常一樣,我從Sphere創(chuàng)建它...
7. 3D動(dòng)畫(huà)軟件你知道幾個(gè)?3ds Max、Blender、Maya、Houdini大比拼
當(dāng)提到3D動(dòng)畫(huà)軟件或動(dòng)畫(huà)工具時(shí),指的是數(shù)字內(nèi)容創(chuàng)建工具。它是用于造型、建模以及繪制3D美術(shù)動(dòng)畫(huà)的軟件程序。但是,在3D動(dòng)畫(huà)軟件中還包含了其他類(lèi)型的...
8. 開(kāi)發(fā)三昧游戲叫什么(三昧動(dòng)漫)
?三昧動(dòng)漫對(duì)于著名ARPG游戲《巫師》系列,最近CD Projekt 的高層回應(yīng)并不會(huì)推出《巫師4》。因?yàn)椤段讕煛废盗性诓邉澋臅r(shí)候一直定位在“三部曲”的故事框架,所以在游戲的出品上不可能出現(xiàn)《巫師4》
9. 3D打印技巧揭秘!Cura設(shè)置讓你的模型更堅(jiān)固
想讓你的3D打印模型更堅(jiān)固?不妨嘗試一下Cura參數(shù)設(shè)置和設(shè)計(jì)技巧,讓你輕松掌握!
10. Unity3D入門(mén):手把手帶你開(kāi)發(fā)一款坦克大戰(zhàn)的游戲
Unity工程創(chuàng)建完成后如圖所示: 接下來(lái)應(yīng)該導(dǎo)入此項(xiàng)目所需的Unity Package文件,要用到的Unity package文件大家可以去Unity3D的官方網(wǎng)站下載(地址:ht...
最新文章
同學(xué)您好!