弱交互移動遊戲伺服器端框架設計

弱交互移動遊戲伺服器端框架設計

4 人贊了文章

原文在 這裡。知乎的排版實在是...

  很早前即有想法設計一套穩定、高效、安全的弱交互移動網路遊戲伺服器端基礎框架,前些天初步完成簡單的初稿文檔。初版設計參考了印象里以前的一些工作經歷經驗。這些經歷經驗雖已日漸模糊,但從它們這裡,自己獲益良多。

  初稿文檔暫只是簡單記錄了目前想到,或覺得比較重要的內容(或許會更新),具體細節等涉及較少。可能我會在業餘時間裡一點點實現本文所述框架,只是開發計劃暫無法預期,畢竟精力很有限。

  1、功能描述

    1.1) 弱交互移動休閑類遊戲伺服器端基礎框架(以房間為遊戲單位,諸如棋牌類遊戲)

    1.2) 相較傳統的 MMORPG 伺服器框架,簡化結構

  2、框架構成

    2.1) LoginGate(登錄網關)

      運行在公網環境,用於轉發客戶端與 LoginServer 間的登錄交互等。LoginGate 如果被攻擊,可新開其它地址(如在別的機房)的 LoginGate。當然也可部署多個 LoginGate。

    2.2) LoginServer(登錄伺服器)

      運行在內網環境,只接受合法的 LoginGate 連接,自身也連接至 DBServer,用於客戶端登錄驗證及登錄狀態管理等。

    2.3) GameGate(遊戲網關)

      運行在公網環境,主要用於轉發客戶端與 GameServer 之間的通訊封包,同時也能處理諸如外掛、惡意連接等(如新連上來的客戶端若 15 秒還不發數據,或若有客戶端以非正常速度發數據則直接踢掉甚至加入黑名單)。

      通常會有多個 GameGate 進程部署在相同或不同的物理機上,甚至可部署在不同的機房。

    2.4) GameServer(遊戲伺服器)

      運行在內網環境,遊戲邏輯核心伺服器,只接受合法的 GameGate 連接,自身也連接至 DBServer,且會通過 UDP 協議發送日誌信息給 LogServer 保存。

    2.5) DBServer(數據伺服器)

      運行在內網環境,主要負責遊戲數據存取、登錄驗證(可選)等邏輯,只接受 LoginServer 與 GameServer 的連接。

    2.6) LogServer(日誌伺服器)

      運行在內網環境,用於保存 GameServer(甚至 DBServer、LoginServer 等)通過 UDP 發過來的日誌信息。

    各伺服器間連接圖如下。

    GameServer、DBServer、LoginServer 及 LogServer 可放在同一區域網甚至同一台物理機上(如果負載不大的話)。通過模塊功能劃分框架構成,各模塊職責明確,代碼結構清晰,對於網路攻擊防範及減輕譬如 GameServer 的壓力等大有裨益。

  3、客戶端進入遊戲流程

    3.1) 客戶端啟動時,向某指定的(固定不變的)地址(域名)發起一個 HTTP 請求,獲取 LoginGate 地址(IP&Port)

    3.2) 客戶端連接至 LoginGate,之後輸入賬號密碼並提交

    3.3) LoginGate 轉發賬號密碼等信息給 LoginServer,由 LoginServer 驗證(與 DBServer 交互)

    3.4) 若驗證通過,DBServer 準備玩家數據,LoginServer 通過(分散式)負載均衡演算法返回某 GameGate 地址,然後 LoginGate 斷開和客戶端的連接

    3.5) 客戶端斷開與 LoginGate 的連接,並連接至 GameGate

    3.6) 客戶端通過 GameGate 與 GameServer 建立起連接並進入&開始遊戲

  4、技術實現

    4.1) 開發技術

      4.1.1) Golang

        遊戲後台開發(至少核心及基礎框架),用編譯型(原生)語言來編寫應是比較合理的做法(譬如強類型語法在編譯期能提前排除很多可能要到線上運行時才能發現的問題)。動態語言當然也能,但明顯這並非它們所長(如代碼組織、代碼可讀性、調試便利度、部署複雜度以及安全和效率等方面)。

Java 等語言技術當然也能,而且可用的資源很多,人才也非常之多,但它帶 VM,部署麻煩,框架厚重,相對而言並不算理想的選擇。

C++ 太複雜(即便只用其很小的一部分子集),對人員的技術要求較高(寫出穩健的 C++ 程序並不容易),編譯太慢,對於中小技術團隊來說並非好的選擇。

而 Delphi,單從其品質中下、人才難尋等方面考慮,更非合適選擇。

至於以替代 C++ 為目標的 Rust,綜合其語言複雜度(似乎至今語法還未成型)及開發支持團隊、社區、使用案例等,至少短期內,可能觀望一下比較合適。

原生、語法簡單且以實用為導向、標準及三方庫強大(譬如網路等方面)、編譯迅速、編譯器優化主流水平(GC 改進已很大且一直在持續改進)、跨平台,說 Golang 是天生的後端開發利器並不為過。

而早已有不少 Web後台、遊戲後端、KV資料庫等(成功)使用案例。

通常情況下,Golang 能比較快上手,熟悉其它語言技術的開發人員轉到 Golang 基本會很快。

      4.1.2) Lua(可選)

        不止在遊戲界,業務邏輯採用腳本語言(較常用的是 Lua、Python 等)來開發非常常見,這種方式的好處在於:

4.1.2.1) 靈活,業務邏輯變動可能較頻繁,而腳本代碼修改執行很方便

4.1.2.2) 劃分核心層和業務層,普通開發人員接觸不到核心的代碼,只能拿到腳本介面文檔用腳本寫業務邏輯

4.1.2.3) 腳本代碼出錯了,最多影響局部邏輯(可上報腳本錯誤以方便後續解決問題),用腳本做一個安全的調用層可以避免整個進程崩潰

4.1.2.4) 熱更新

綜上,採用 Golang + Lua 相結合的方式,或許不失為可嘗試的開發模式。

      4.1.3) Protobuf(可選)

        高性能的網路傳輸協議格式,序列化及反序列化速度甚至遠勝 JSON、XML 等,其簡單、精簡(數據描述文件非常小),不依賴於平台,支持多種編程語言。但其實,自實現緊湊高效的封包格式也並不難。

      4.1.4) 加解密

        PC 網遊一般採用 動態加解密模式(編寫數套加解密演算法並編譯,然後摳出每套加解密函數的機器碼,每次客戶端上線時,隨機選取一套加解密演算法發給客戶端,之後客戶端與伺服器的通訊封包皆通過此演算法加解密),但移動遊戲估計不容易實現。

如果封包較小且不密集,可考慮採用不對稱加解密演算法,增加封包破解難度。

否,應考慮 TEA、AES 等對稱加解密演算法(如 QQ 的聊天信息本質上就是用 TEA 加密的)。

譬如可考慮隨機使用幾種加解密演算法中的一種(每次客戶端上線時,伺服器通過約定的 ID 告知應使用哪套加解密演算法),增加靈活性及破解難度。

    4.2) 資料庫存儲

      4.2.1) MySQL Community x64

4.2.2) MongoDB(備選)

    4.3) 運行平台

Linux 64bit(CentOS / Red Hat)

  5、後記

    以上思路,是以單個的遊戲為設計立足點,較有局限。

    譬如登錄,統一走登錄平台的方式更通行及合理(此時可由 LoginGate 與 平台進行交互驗證)。而日誌處理等,能有專門的處理後台也不失是好的做法。

    只是如此會涉及很多方方面面的細節和做法,於初衷有悖,是以本文所述設計,僅供參考而已。但很明顯,基於以上設計,縱使需作擴展,改進起來也較簡單(畢竟,此伺服器框架專為弱交互移動遊戲而設計)。

  6、一些討論

    與某基友討論如斯設計,基友認為無需三層結構(Client-->GameGate-->GameServer),而是讓客戶端直連 GameServer(GameServer 負責邏輯處理,可以線性擴展),且加一個中央伺服器(CenterServer),做簡單的遊戲狀態記錄和邏輯處理,以及支配各 GameServer 等。這種設計當然很好,只是在考慮到諸如框架簡明及伺服器安全等因素,短期內估計無意以此思路來改動初版設計。
推薦閱讀:

TAG:Go語言 | 遊戲伺服器 | 伺服器架構 |