五邑隱俠,本名關健昌,10年游戲生涯,現隱居海邊,
本教程以Go語言磁區游戲服務端框架搭建為例,
Go語言是Google開發的一種靜態強型別、編譯型、并發型、具有垃圾回收功能的編程語言,語法上近似C語言,支持介面、可通過struct包含另一個struct方式實作繼承等面向物件的概念,性能上媲美C/C++,相比C/C++更健壯,更易開發并發程式,我以前也寫C++服務端,接觸Go后,更傾向用Go做游戲服務端開發,
所謂磁區游戲,指游戲將分為很多個區,不同區之間玩家不能互動或只有少量互動,玩家進入游戲需要選擇磁區,進入指定磁區進行游戲,一個玩家可以同時在不同磁區有角色,目前市面上大多中重度網路游戲都采用這種模式,磁區游戲適合不需要大DAU互動的游戲,如卡牌、MMORPG、SLG等,從技術層面,磁區屬于集群擴容的一種手段;運營上,有利于磁區精細運營,滾服運營已經是比較成熟的游戲運營手段,相對磁區游戲,也存在不磁區的社交游戲,這類游戲核心玩法是匹配對抗,例如COC,如果把磁區游戲的磁區,映射為該類游戲的節點服,廣播服映射為匹配服,對不磁區游戲的架構也就很好理解,
本教程主要講磁區游戲服務端框架搭建,總體設計如下:

磁區游戲,玩家先登錄游戲,然后進入指定磁區,所以首先要有一個登錄服務器,提供全域的登錄服務,登錄服務器的核心資料是玩家賬號,核心業務是對玩家進行登錄校驗,包括使用自有賬號系統、第三方賬號登錄,賬號資料需要落地長期存盤,所以在該服務器配套一個MySQL資料庫,用于保存玩家賬號資訊,有一到多個登錄服務行程,進行游戲登錄校驗,登錄服務是一個短連接服務,使用http協議,對外通過nginx提供統一訪問地址,對多個登錄服務行程做負載均衡,通常,登錄介面還會回傳磁區資訊、玩家各磁區角色簡要資訊、客戶端最新版本號、配置版本、資源版本、公告等,這些資訊可以通過gm服務(后面會介紹)動態更新,登錄服在回應請求時獲取并回傳給客戶端,所以在登錄服務器會配套一個redis服務,用于這些資料的快取,
玩家登錄游戲成功后,將進入選定游戲磁區,磁區是一組服務行程,大部分游戲磁區都采用長連接通信,如果同時兼顧現在熱門的h5游戲、微信小游戲,考慮選用websocket做通信(以前使用socket),考慮到游戲中會有廣播的需求,廣播資料和磁區游戲資料都希望從同一個連接回傳給客戶端,有必要提供一個統一的磁區入口網關服,網關服行程對客戶端提供統一的磁區地址和埠,對內做資料轉發,磁區的邏輯業務可以集中放在一個游戲服行程里,以前一些游戲,游戲服在線資料會保存在行程記憶體里,由于游戲資料變化太頻繁,MySQL 頻繁讀寫性能不高,所以會隔一定時間才保存到MySQL,但磁區內游戲服是一個單點,一旦崩掉,游戲服的記憶體資料就會丟失,回檔到上一次保存的時間,后來一些游戲為了減少這種風險,把在線資料保存到共享記憶體,再定時保存到MySQL,共享記憶體依賴系統和語言,目前發現Go沒有直接支持,再后來有了memcached和redis,部分游戲選擇用這種快取系統做快取,游戲服崩掉,資料還在快取里不會丟失,可以快速啟動游戲服恢復服務,我選用redis作為快取,快取活躍玩家資料,隔一定時間,把變化資料保存到MySQL,redis資料主要使用key-value方式保存資料,每次業務處理都需要讀取、決議,再使用,對業務開發不是很友好,游戲服行程記憶體還是會保存在線玩家資料,玩家進入磁區時從redis讀取到游戲服記憶體,redis不命中則發布訊息給資料服進行資料預熱,預熱成功后從redis讀取,后面的請求可以直接通過記憶體資料做業務判斷、處理,更改資料以事務方式保存到redis,成功后回應給客戶端,這樣記憶體資料跟redis資料一致,而且可以把玩家資料拆成更細的單元,減少跟redis間的通信,玩家下線后清除游戲服記憶體資料,所以磁區內配套一個redis、一個MySQL,為了建立定時保存資料這個機制,且不會因游戲服崩潰而受影響,配備一個功能很簡單的資料服,通過redis的發布訂閱機制、訊息佇列,負責資料的定時落地固化、玩家注冊、資料預熱,
前面提到廣播服,廣播服顧名思義主要負責廣播,例如跑馬燈廣播、世界聊天、世界boss,廣播服通過各個磁區的網關服將資料廣播給玩家,因此廣播服將連接各個磁區網關,廣播任務通過訊息佇列進行快取,這樣每個磁區的廣播操作在寫到佇列后就可以回應客戶端,訊息佇列采用redis實作,廣播服是一個全域的服務,為了避免單點風險,可以做成主從,通過redis的訂閱發布機制,啟動時訂閱redis,如果一定時間沒有收到發布訊息,認為主服務不存在,切換為主服務,取消訊息訂閱,連接各磁區網關,定時向redis發布訊息報活,
除了業務相關的服務,需要對整個服務體系提供管理,例如開服、停服、更新配置/資源版本、發郵件、發公告、發放道具、踢人等,提供一個全域的gm服,各磁區服務啟動后,游戲服行程連接到gm服并保持心跳,以通知gm服開/停服,gm服將這些變更資訊更新到登錄服的redis,這樣玩家登錄游戲就知道各個服的狀態,gm服還可以通過向redis發訊息通知登錄服進行封號等操作,由于各個游戲服都連接到gm服,這樣就可以對各個磁區發gm命令,gm服可以通過向廣播服的訊息佇列寫訊息發全員廣播,gm服的功能由運營人員進行操作,所以需要提供http服務,方便在網頁上訪問,gm服有道具發放的功能,所以第三方支付回呼可以通過gm服的http介面請求發貨,
為了給運營提供決策,還需要提供統計后臺,對游戲資料日志進行收集、統計,由于登錄服、各磁區的游戲服、gm服都會上報資料,資料來源廣,資料量大,需要做訊息佇列,因此登錄服、游戲服、gm服都通過redis的訊息佇列進行上報,統計服從redis讀取訊息,保存資料日志到MySQL,因此需要配套一個redis、一個MySQL,統計服的功能由運營人員使用,需要提供http服務,方便在網頁上訪問,統計服的http介面還支持客戶端進行資料上報,
為了合并運營人員的頁面,gm服、統計服通過nginx提供統一的http地址,
這樣就得到了如前面設計圖的整個服務框架,
本篇介紹到這里,接下來會詳細介紹各個服務的實作,在此之前,下一篇先介紹一些通用的基礎機制設計和實作,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/56920.html
標籤:Go
