咱們最開始作的遊戲框架,多數都是client—>server—>db的模式,可是隨着玩家數量的增長,一個server進程就會扛不住,須要多個進程服務於多個玩家。可是給定了不一樣進程的玩家,有可能須要交互,這就致使了client與server端的鏈接,有多是o(1),但也多是o(n)鏈接,o(n)的擴展性很是差,不容易維護,所以能夠剔除了。可是若是隻保持o(1),那必然要引入新的抽象服務,網關也就登場了。下圖是一個簡單的網關部署架構:
網關的引入,有哪些改變呢?
- 內外網解耦,在保持客外網客戶端不變的狀況下,能夠經過這個中間層調整內網服務的實現
- 規範化,因爲請求是網關統一接受和分發的,會直接促使客戶端在發送和接受請求時規範化
- 安全,因爲網關具備收口做用,全部的安全問題均可以在這裏解決,保護內網,好比反爬,認證等功能
- 限流熔斷,在網關上實現限流,避免內網被突發流量壓垮
- 統一的監控告警平臺
有了網關後,開始在下游增長業務邏輯,可能咱們會把全部的業務都耦合成一個service,好比聊天掛了,派系掛了,場景掛了,均可能會對有戲自己產生影響;基於此,不得不考慮拆分進程,以前的遊戲service服務,可能會被拆分爲多個服務,可是對於大多數的遊戲開發人員來講,基於服務的開發,比基於進程的開發,也難的多,若是不是領導推動,也不會有人願意把聊天作成一個單獨的服務。
對於遊戲來講,服務拆分最最極端的狀況,就是一個消息cmd對應了一個service,可是這種狀況會致使service愈來愈多,沒法維護的程度,實際上游戲拆分也確實沒有必要。不過服務service愈來愈多,某個service甚至處於內存,cpu瓶頸的狀態,應該如何解決呢?這時候rpc的服務治理派上了用場。咱們對上面的圖示作下改動:
game-rpc的引入,解決了哪些問題呢?
- 開發人員再也不須要關注內部通訊機制,減小項目開發時間,下降成本
- 強大的集羣容錯,負載均衡能力等,保證每次調用都能路由到合適的節點
service與service作成了集羣,每一個service啓動後,往zk或nacos註冊中心註冊本身的url。gateway在啓動後,訂閱zk註冊中心的service列表,依託於rpc自己強大的集羣,負載等功能,能夠自動實現service的切換。
在針對rpg等長鏈接遊戲類型時,玩家在場景中的移動都須要同步,廣播給周圍的玩家,可是rpc是單通道的,不能回傳,這應該如何處理呢?
有借於此,game-rpc增長了全雙工的概念,不只僅是client對service的請求,同時service也能夠根據uniqueId,進行主動推送。因而上面的流程圖變成了下面這樣:
一切看上去都很完美,彷佛沒有問題了,然而新的問題隨之出現。
咱們知道,優秀的架構體系中,單點問題是不能容忍的,很不幸,咱們的gateway,就出現了單點。隨着玩家數量的增長,整個服務都會處於不可用的狀態。因而網關須要拆成集羣的模式,新的架構圖顯示以下:
網關拆分後,gate1和gate2的玩家是兩個tcp長連狀態的服務,沒法交互,這應該怎麼辦?
咱們參照了現行市面上比較經常使用的tcp網關作法,消息下行通知的解決方案,目前框架支持了兩種方式:
- MQ廣播機制,當某臺網關服務器收到廣播消息後,MQ通知給集羣內的全部gate server,每一個gate在收到消息後,判斷要推送端的消息是不是當前gate所持有的會話,若是在當前服務,則進行推送,不然拋棄
- redis session共享,針對MQ的廣播機制,若是之後遊戲火爆,同時有百萬玩家在線,那麼gate集羣裏的機器,可能會達到上百臺不等,若是每一個消息都須要MQ廣播,有可能會致使信號風暴,因而咱們調整了最後一種解決方案。玩家在登陸網關,認證成功後,把玩家id做爲key,當前鏈接的網關uniqueId做爲value,存儲到redis集羣中。網關隨後把消息路由到具體某個service,service從redis集羣裏獲取到須要廣播的玩家對應的gate服務,service經過rpc消息下行,直接推送到具體的gate,再由gate轉發到client
說明:這種架構,更適用於全區全服類型的遊戲。目前咱們已經有多款線上遊戲使用。
更多交流,也歡迎您關注個人微信公衆號: