網絡游戲服務器構架設計(二):刀劍Online - 連接負載服務器CLS


    本文並沒有涉及什么逆向工程,只是拜讀刀劍Online服務器端主程的文章后[1],想結合自己的經驗談一談。

PS:由於題目范圍太大,本系列的前言做了一些限制。

 

一、網絡游戲服務器

    要想設計好網絡游戲服務器的構架,首先需要知道網絡游戲服務器在玩家游戲過程中發揮什么作用。就我個人的理解:網游服務器在玩家游戲過程中扮演上帝的角色。玩家在服務器制定的規則下進行游戲,服務器負責同步在線玩家之間的屬性、操作、狀態等等,最終在多個不同的客戶端呈現一個“統一”的游戲世界。

    所謂的服務器構架在本系列blog中,主要是指如何將服務器各部分合理的安排,以實現最初的功能需求。好的結構不是一蹴而就的,是通過需求的推動一步步的完善。而且每個設計者心中的標准不盡相同,所以我認為並沒有絕對優秀服務器構架。本系列文章中所謂的優秀構架是指各方面達到一種平衡(包括成本等的非技術因素)。

    下面先介紹刀劍Online的服務器構架(后續還可能有WOW、天龍等):

 

二、刀劍Online

image    

圖1 刀劍Online服務器構架

 

    看了像素的技術總監魏華的文章[1],感覺有點意思。文章中所介紹的服務器構架並不復雜,但滿足一般MMORPG網游要求應該是綽綽有余了。按照魏華自己的話,這樣的服務器構架主要滿足能夠接受以下幾條限制的網絡游戲:

  1. 游戲同時在線人數在1w人以下。
  2. 服務器為多進程程序,可部署在一台或者多台機器上。
  3. 服務器內存足夠大,一般一個進程1~2G的內存需求還是應該滿足的,64位系統能支持更大的內存需求。內存這塊主要看游戲的設計需求。
  4. 刀劍屬於格斗性質的網游,對CPU和帶寬有一定的要求。(這篇文章寫於2005年,當時刀劍可能是按照256k、512k或1M ADSL的網速進行設計的。現在已經開始普及10M網,帶寬和網速應該可以滿足),網絡延遲的問題本文后面再做展開。對CPU的要求主要影響可承載人數。
  5. 地圖采用獨立小場景的管理模式,各個場景之間通過傳送點來連接。每個場景服務器程序分管一部分地圖。

    服務器包括游戲中和游戲外兩大部分,這里主要討論游戲中的服務器構架,類似客戶端自動更新等的游戲外服務器不在本文的討論范圍。

    接下來對刀劍Online的服務器構架的各個部分進行詳細的分析,其中包含很多我自己的想法,很多內容都是我猜測的,因此不能“信以為真”。

 

2.1 連接負載服務器(Connection Load Server,CLS)

    游戲客戶端在游戲過程中實際上是和連接負載服務器(簡稱CLS)進行連接並做數據交互的。如文中[1]所訴,CLS主要的作用是:

  • 把網絡連接和真正的游戲邏輯隔離開,降低游戲邏輯服務器處理網絡交互的負擔,同時提高游戲的安全性。有了CLS,刀劍Online的服務器對於玩家來說就是一個黑盒,如下圖:

image 圖2

  • 使場景服務器(Zone Server)更為獨立——客戶端連接CLS而不是直接連接Zone Server的好處是:用戶切換場景服務器時,並不會導致原來的TCP連接斷開,從而使設計更為簡單和獨立。
  • 提高發送廣播消息的效率,比如需要全服廣播時,游戲邏輯服務器只需要對CLS發送一條廣播指令,而向每個用戶的廣播工作由CLS完成。
  • 完成客戶端數據交互的加密解密過程。

連接服務器的主要工作正如上述魏華談到的,但有幾點並沒有做出強調,下面本人結合平時的實際工作給出一些補充(不一定正確):

根據經驗:

    CLS作為與client建立連接、進行數據交互的“Gate”,從程序角度來看CLS的代碼應該是最簡潔高效的。因為CLS主要負責與客戶端交互數據是的加密解密、以及數據搬運。而使用流加密算法RC4對整個數據流進行加密解密是很耗CPU的,因此代碼的高效在這個模塊是十分的重要。

    為了提高程序的運行效率,CLS程序往往會使用-O3的選項進行編譯,這無形中又對代碼的編寫有更高的要求。CLS一般會有自己的打包機制(控制發送頻率),因此常會使用TCP_NODELAY選項禁用Nagle算法。

    CLS常會被分配到不同的物理機器上,因為操作系統在處理TCP包時,需要通過軟中斷來通知進程或者喚醒system call,在服務器十分繁忙的時候CPU可能處理不過來。解決辦法是:使用多核的服務器,然后把TCP的軟中斷平均分配到多個CPU。(一些操作系統默認只使用0號CPU來處理,Fedora Core release 2默認就是只使用0號CPU,較新的版本我沒有做研究)

    CLS在做數據流的解密后,往往需要把數據包構造成內部服務器進程間通訊使用的protocol,這種protocol模塊要獨立,序列化和反序列化的接口要穩定,這樣以后需要更換協議模塊也不至於傷筋動骨。可以使用像google的protobuf這樣的開源協議,減少開發難度。

    CLS負責建立和client的連接,多會使用多個CLS進程才能支撐1w的在線人數,因此在CLS前端一般會有負載均衡的程序,負責把建立連接的請求均勻的提交到各個CLS。

   有一個需要討論的問題:作為服務器端的“Gate”,只負責數據轉發的CLS是否需要對client發過來的數據進行完全的解密?或者只解密包頭,知道轉發的目的地即可?(RC4並沒有增加流的長度,因此可以只做部分解密)

  CLS只做部分解密:

好處:將耗費CPU資源的解密功能分攤到別的進程;各進程各服務可以在解密后用不同的方案來構造自己的protocol。

  CLS做完全解密:

好處:可以提前過濾部分無效的消息,只做部分解密也可以做提前過濾,但是這樣太過於依賴協議的設計;在CLS處做完全解密,則往后服務器端的之間的消息傳遞都是明文,利於抓包查錯;由於CLS的功能比較簡單,很容易通過加機器來進行擴展,因此計算放在CLS上是比較明智的選擇。

 

總結

    CLS是一個功能相對簡單但要求代碼簡潔高效的程序,在設計實現的時應該注重效率及代碼編寫規范。經過對比在CLS程序對數據流進行完全解密是利大於弊的,推薦使用這種方案。

 

 

2.2 ...................待續

    (2.2節及后續章節將寫在后面的文章里)

 

 

References: 

[1]像素軟件技術總監--魏華:《刀劍Online服務器構架分析》


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM