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