五邑隐俠,本名關健昌,10年遊戲生涯,現隐居海邊。
本教程以Go語言分區遊戲服務端架構搭建為例。
Go語言是Google開發的一種靜态強類型、編譯型、并發型、具有垃圾回收功能的程式設計語言。文法上近似C語言,支援接口、可通過struct包含另一個struct方式實作繼承等面向對象的概念。性能上媲美C/C++,相比C/C++更健壯,更易開發并發程式。我以前也寫C++服務端,接觸Go後,更傾向用Go做遊戲服務端開發。
分區遊戲,指遊戲将分為很多個區,不同區之間玩家不能互動或隻有少量互動。玩家需要選擇分區進入指定分區開始遊戲,一個玩家可以同時在不同分區有角色。目前市面上大多中重度網絡遊戲都采用這種模式,分區遊戲适合不需要大DAU互動的遊戲,如卡牌、MMORPG、SLG等。從技術層面,分區屬于叢集擴容的一種手段;營運上,有利于分區精細營運,滾服營運已經是比較成熟的遊戲營運手段。分區的基礎上,可以按相鄰分區編号設定跨服服務,例如10個分區一組設定跨服服務,用于跨分區的玩法。相對分區遊戲,也存在不分區的社交遊戲,這類遊戲核心玩法是比對對抗競技,例如COC。簡單的比對競技遊戲可以把分區遊戲的分區改為節點,把跨服服務拆分成比對服務和多個競技服務,比對服務隻做簡單的報名和比對,比對成功後把玩家配置設定到指定的競技服務,并在裡面配置設定房間開始遊戲。
搭建分區遊戲服務端架構,首先建立一個服務注冊發現機制。我們以注冊服作為機制的核心,提供服務注冊,以及服務資訊廣播。作為遊戲主體,分區的遊戲服務組是注冊的對象。遊戲服務組的主服務“遊戲服”啟動成功後,連接配接注冊服,并注冊該服務組。這樣注冊服知道所有分區的基本資訊和狀态。分區注冊後,有哪些服務需要發現分區、關注分區的狀态變化?對于玩家,登入後要知道有哪些分區以及狀态情況。是以賬号服需要發現分區。玩家通過登入傳回知道分區情況,選擇分區進入遊戲。而玩家是通過網關連接配接分區的,是以網關需要發現分區。分區注冊後,需要切換狀态來支援開服測試、開服、維護。一般會搭建一個管理服,營運人員可以通過管理服發指令給分區更改狀态。是以管理服也需要發現分區。這樣得到第一個架構模型如下:

按照這個模型,先啟動注冊服等待其他服務注冊。然後分别啟動管理服、賬号服、網關,這些服務注冊到注冊服。新開一個分區就啟動該分區遊戲服務組,分區狀态為開服測試。該分區連接配接并把狀态資訊發給注冊服。注冊服通知管理服、登入服、網關該分區狀态變化。網關連接配接該分區的遊戲服。這時候測試賬号可以登入進入該分區開始測試。測試通過後管理服可以發指令更改該分區狀态為正常正式開服,分區更新狀态并發送給注冊服進行廣播。同理當分區需要維護時,管理服發指令給該分區更改狀态為維護。網關收到注冊服廣播後,斷開與該分區服務的連接配接,等待一段時間後該分區的服務可以關閉進入維護。這樣一個注冊發現的流程算是跑通了。
服務間除了注冊發現關系外,它們也互相連接配接調用。下面來分析一下各服務間關系。賬号服不與其他服務保持連接配接。對用戶端提供http登入,通過使用同一key對稱加解密token,實作帳号服和遊戲服間跨服務校驗。每個用戶端與一個網關保持長連接配接。對于通信量和頻率不高的卡牌遊戲,為提高網關複用,可以讓每個網關都連接配接所有可進入的分區遊戲服務組,用戶端連接配接任一網關都能進入所有可進入的分區。遊戲服務組的業務請求主要由用戶端通過網關轉發過來,小部分為管理服發送過來的gm指令。管理服連接配接所有遊戲服務組,對外提供http請求,将gm指令轉發到對應的遊戲服務組。這樣得到第二個架構模型如下:
接下來看看分區的服務怎樣劃分。先看一個簡單的情況。分區有一個主服務,負責注冊到注冊服、處理玩家的基本請求,包括分區登入、玩家基本資訊操作、養成等業務。這些業務都需要頻繁修改玩家資料,應避免直接操作資料庫,是以使用redis做緩存,主服務直接操作redis上的資料。redis資料要有一個落地的機制避免redis崩潰或資料過期後資料丢失。這裡選用mysql做固化資料庫,玩家的遊戲資料會從redis固化到mysql。對于redis上資料已過期的玩家再次登入,還需要把資料從mysql加載到redis。是以這裡增加一個資料服,負責資料的預熱和落地。一個基本的流程,玩家進入分區,主服務處理請求,從redis擷取玩家資料,redis上不存在該玩家資料,主服務通過redis釋出消息給資料服預熱該玩家資料,資料服查詢mysql,如果mysql沒有該玩家資料,資料服往mysql新加一條玩家資料注冊個新玩家,資料服把玩家mysql的資料添加到redis,資料服釋出消息通知主服務該玩家資料已準備好,主服務繼續從redis擷取該玩家資料,傳回給用戶端。後續的業務請求,主服務讀取redis的玩家資料進行業務處理、回寫redis,釋出消息給資料服該玩家redis資料有更新,傳回響應給用戶端。資料服定時将有更新的玩家redis資料儲存到mysql。這樣分區的基本流程也能跑通。
除了基本流程,分區可能需要廣播消息,例如世界聊天、系統公告。在分區搭建一個廣播服,在redis裡維護一個廣播隊列,主服務往廣播隊列裡添加廣播消息,廣播服從廣播隊列裡拿消息進行廣播。對于MMORPG,還需要有場景服管理各個遊戲地圖,回合制的卡牌、MMORPG遊戲需要有單獨戰鬥服進行戰鬥的預演。如果有跨服玩法,還需要有跨服服務,相鄰幾個分區共用一個跨服服務。這樣得到的分區服務模型如下:
這樣一個基本的遊戲服務端架構輪廓就出來了。接下來需要封裝一些公共基礎功能,以便快速搭建各個服務