隨著游戲市場的興起,特別是網(wǎng)頁游戲、手機游戲的崛起,對游戲開發(fā)技術(shù)的需求越來越多。網(wǎng)絡(luò)游戲開發(fā)是一個龐大的體系,總體來說是客戶端與服務(wù)器端。客戶端是玩家接觸的游戲圖像顯示端,服務(wù)器是處理游戲運行中的各種數(shù)據(jù),由于一臺服務(wù)器要支持眾多玩家的請求,所以服務(wù)器的性能高低決定了同一個游戲的用戶數(shù)量。
我們公司選擇使用Java做服務(wù)器開發(fā)語言,主要原因是:1.Java是跨平臺的,方便部署;2.Java是安全的高級語言,可以提高開發(fā)效率;3.Java是面向?qū)ο蟮?,代碼可以重用;4.Java的分布式應(yīng)用。
圖1服務(wù)器架構(gòu)圖
服務(wù)器架構(gòu)
Java在我們的服務(wù)器開發(fā)中的應(yīng)用。服務(wù)器架構(gòu)如圖1所示。服務(wù)器架構(gòu)的幾個模塊:
登錄服務(wù)器
邏輯服務(wù)器
用戶中心服務(wù)器
充值服務(wù)器
數(shù)據(jù)庫服務(wù)器
日志服務(wù)器
這些模塊都是分開的,可以靈活地分布式部署到不同的物理服務(wù)器上。只需要修改一些配置文件即可,非常方便。
服務(wù)器詳細功能模塊
登錄服務(wù)器
負責(zé)處理玩家登錄的請求。一個登錄服務(wù)器對應(yīng)多個游戲邏輯分區(qū)。當玩家登錄的時候,登錄服務(wù)器向用戶中心服務(wù)器發(fā)送登錄信息。請求對登錄信息的驗證。通過驗證之后,返回分區(qū)地址,之后,客戶端與登錄服務(wù)器斷開,連接到游戲邏輯服務(wù)器。登錄服務(wù)器是一個單獨的Java運行程序,當訪問量增加大,可以增加部署到多個物理服務(wù)器上面,均衡負載訪問壓力。它通過使用Java的NIO(非阻塞)方式與客戶端進行通信。通過用戶中心服務(wù)器提供的接口訪問用戶中心,進行數(shù)據(jù)處理。
邏輯服務(wù)器
對玩家的操作進行邏輯處理。邏輯服務(wù)器是整個游戲的心臟。它的工作效率直接影響玩家在游戲中的體驗,所以對它的要求就是速度,快速返回處理結(jié)果。為了達到滿足要求的速度,邏輯服務(wù)器的大部分操作必須在內(nèi)存中操作,避免I/O操作,I/O操作可以放到另外的線程中進行。說是大部分,是因為玩家在第一次登錄的時候可能會從數(shù)據(jù)庫加載所要用到的數(shù)據(jù)。在圖中,大家看到了緩存,緩存的作用就是把數(shù)據(jù)放在內(nèi)存中。當玩家退出時,它的數(shù)據(jù)也會在緩存中保存一段時間,在一定時間內(nèi),玩家再次登錄,將不會再重新從數(shù)據(jù)庫加載數(shù)據(jù)。在邏輯服務(wù)器中對數(shù)據(jù)庫的操作可以先放入一個Java隊列中,再另起一個Java線程負責(zé)從這個隊列取數(shù)據(jù),并發(fā)送到數(shù)據(jù)庫服務(wù)器,這就是使用Java的阻塞隊列,快速實現(xiàn)一個生產(chǎn)者—消費者模式,數(shù)據(jù)生產(chǎn)與處理相分離,這樣既減輕了邏輯服務(wù)器的壓力,也保證了數(shù)據(jù)處理的效率。邏輯服務(wù)器的日志也不在邏輯服務(wù)器入庫,同樣的發(fā)送到日志服務(wù)器處理。還有一種方法是以一種特定格式的方式,記錄到本地文件中,再啟動一個進程,讀取這個文件,然后入庫。
用戶中心服務(wù)器
現(xiàn)在很多游戲都對用戶進行了集中管理。這方便了對用戶提供更好的服務(wù),比如充值、活動、禮包領(lǐng)取、新游戲?qū)胗脩舻?。有的游戲公司可能會用用戶中心的?shù)據(jù)發(fā)展游戲運營平臺。這部分與游戲邏輯服務(wù)器分開,也減少了游戲邏輯服務(wù)器的壓力。用戶中心采用JavaWeb開發(fā),它對游戲服務(wù)器只提供特定訪問的接口,把數(shù)據(jù)與邏輯分離開來,方便管理,以及分布式部署,增強了架構(gòu)的靈活性。
充值服務(wù)器
充值是游戲收入的唯一方式,所以這個功能必須流暢,毫無壓力。如果由于網(wǎng)絡(luò)或服務(wù)器性能原因,導(dǎo)致玩家充值不了,會直接影響收益的。所以充值服務(wù)器最好部署在一臺單獨的物理機上面,也可以多個分區(qū)使用一個充值服務(wù)器,這要視游戲人數(shù)而定。
數(shù)據(jù)庫服務(wù)器
負責(zé)對數(shù)據(jù)入庫及更新的操作。把這部分操作從邏輯服務(wù)器分離出來,就是為了減輕邏輯服務(wù)器的壓力,減少邏輯服務(wù)器資源的占用。而且,如果邏輯服務(wù)器突然宕機的話,也能盡量保證數(shù)據(jù)少丟失。為了保證對數(shù)據(jù)的更新是順序性的,這里把數(shù)據(jù)入庫的操作使用隊列單線程化。邏輯服務(wù)器與數(shù)據(jù)庫服務(wù)器通過Java的TCP/IPSocket進行長連接,而且為了防止由于意外原因?qū)е逻B接中斷,在邏輯服務(wù)器與數(shù)據(jù)庫服務(wù)器之間加入了一個心跳連接,這樣短暫的中斷可以被很快恢復(fù),防止數(shù)據(jù)的丟失。
日志服務(wù)器
處理玩家日志的入庫。日志入庫方便游戲運營管理游戲,統(tǒng)計玩家信息。當玩家人數(shù)比較多的時候,日志也會占用很多資源。所以把日志從邏輯服務(wù)器也分開了,因為日志只是插入操作,所以可以開幾個線程進行并發(fā)插入到數(shù)據(jù)庫。線程數(shù)要根據(jù)你數(shù)據(jù)庫的連接池的最大連接數(shù)進行設(shè)置,要不然會導(dǎo)致連接資源被占完,數(shù)據(jù)插入不了數(shù)據(jù)庫。
注意事項
在游戲服務(wù)器開發(fā)中,有幾個需要注意的問題。
通信協(xié)議
開始的時候,我們?yōu)榱丝焖匍_發(fā),采用了JSON的變長協(xié)議處理方式,即把要傳送的數(shù)據(jù)編碼成json的字符串,再把json字符串轉(zhuǎn)化為字節(jié)數(shù)據(jù),傳輸過程中包的總結(jié)構(gòu)為:總包長度(int四個字節(jié))+消息長度(int四個字節(jié))+消息體,即數(shù)據(jù)長度,n個字節(jié)。這樣做的好處是可以快速開發(fā),缺點是在傳輸過程中無效的字節(jié)太多。而且這部分完全可以用代碼自動完成。后來我們采用Java的反射機制,從定義好的xml描述協(xié)議文件中讀取傳輸?shù)膬?nèi)容格式,自動化生成傳輸?shù)膶ο?,在發(fā)送信息時,根據(jù)這個對象再把數(shù)據(jù)轉(zhuǎn)化為二進制的數(shù)據(jù)流,解析的時候,同樣也根據(jù)xml的描述文件,按順序讀取數(shù)據(jù)并轉(zhuǎn)化為對象的JavaBean對象。如果時間充足,在游戲開發(fā)前期應(yīng)該把這個做好。
多線程并發(fā)
游戲服務(wù)器是一個多用戶的環(huán)境,其中多線程是必不可少的,它可以提交程序?qū)PU的利用率,提高處理性能。但它也有一個致命的缺點,就是在多線程下,數(shù)據(jù)同步的問題。因為在目前多核CPU下,線程算得上是可以并行執(zhí)行的了。比如競技場中的排行榜,每個玩家的名次變化都會對排行榜進行操作。如果不考慮數(shù)據(jù)同步的話,每個玩家可以隨意更新排行榜,那這個排行榜的數(shù)據(jù)就會非常亂,名次也不正確。這個時間就需要保證在一個玩家更新排行的時候,其他玩家不能更新,只能阻塞等待。一般有兩種方法可以解決:1.直接使用鎖,當一個玩家更新排行榜時,使用鎖鎖定排行榜集合,讓其他玩家不能再對排行榜操作,Java有自帶的兩種方式,非常方便,一個是Lock接口,一個是Synchronized;2.使用樂觀同步,這種方式需要自己額外實現(xiàn),之所以說是樂觀,是因為它有可能執(zhí)行失敗。原理是當我取數(shù)據(jù)時,獲得一個數(shù)據(jù)的一個版本號,而當寫入數(shù)據(jù)時,如果版本一致,可寫入,如果版本不一致,就需要重新獲取數(shù)據(jù),執(zhí)行邏輯,直到版本一致后寫入??梢栽O(shè)定重復(fù)次數(shù),達到這個次數(shù)后,還沒有成功就判定失敗。根據(jù)我們目前的運行環(huán)境,我們采用了第一種方式。
均衡負載
一臺物理服務(wù)器的處理能力是有限的,對于可能支持數(shù)據(jù)眾多的游戲服務(wù)器來說,分布式部署和動態(tài)添加服務(wù)器是不可缺少的。在邏輯上,可以把需要集中處理,與邏輯運算關(guān)系不大的模塊單獨部署。比如登錄服務(wù)器、地圖服務(wù)器、聊天服務(wù)器、數(shù)據(jù)庫服務(wù)器等。像我們把登錄服務(wù)器和數(shù)據(jù)庫服務(wù)器分離開就是為了減少邏輯服務(wù)器的壓力。
緩存的設(shè)計
起初,為了快速敏捷開發(fā),我們采用了一級緩存方式,即圖1中的Redis緩存,它是一個分布式的緩存,內(nèi)部通過Socket連接。在玩家第一次進入游戲的時候會把玩家數(shù)據(jù)從數(shù)據(jù)庫加載到Redis緩存之中,再取數(shù)據(jù)只從緩存中取。后來為了更加提高處理速度,增加了二級緩存,即內(nèi)存緩存,利用Java提供的Map、List等集合保存數(shù)據(jù),開發(fā)了一個基于內(nèi)存的緩存構(gòu)架MemoryCacheTool,對外只提供操作接口。由于是直接從內(nèi)存中讀取或?qū)懭霐?shù)據(jù),其速度相對于Redis提高大約20%左右。
總結(jié)
Java是一門安全、高效、跨平臺的語言,它在游戲服務(wù)器開發(fā)過程中可以提高開發(fā)效率,減少異常,增強程序的健壯性。它很容易實現(xiàn)各個功能的銜接,方便后期的維護。
以上就是動力Java培訓(xùn)機構(gòu)小編介紹的“Java在游戲服務(wù)器開發(fā)中的應(yīng)用”的內(nèi)容,希望對大家有幫助,如有疑問,請在線咨詢,有專業(yè)老師隨時為你服務(wù)。