skynet遊戲服務器框架分享

分享下我之前做的服務器框架;  遊戲在線最高3萬;  物理機I7的3台阿里雲分服;性能及其強勁;

框架: 底層基於比較流行的skynet,基礎採用c語言,腳本lua,部分服務golang;

Skynet: 是一個基於C跟lua的開源服務端並發框架,這個框架是單進程多線程Actor模型。所以他對於機器的性能壓榨是很高的。

  1. skynet為遊戲主邏輯服務;  
  1. go微服務作為輔助服務; 
  1. redis作為直連主數據層;
  1. mysql作為冷備+關係查詢;
  1. proxy支持tcp,udp,websocket(支持http和https)
  1. 通信協議Protobuf

特點:

1. 性能: 底層採用了多線程+多luastate+協程, 性能優秀

2. 簡單: 採用了actor模型,並發無鎖,上層coding無感知

3. 沙盒: 利用多線程中lua coroutine的應付IO密集型的優秀能力; 也用lua沙盒做到了環境的軟隔離;

 

缺點:

未引入分佈式的zookeeper協調控制,採用了world的單點模型,容災性較差,服務發現也比較原始;

 

 

前端:

proxy:
代理層; 獨立進程部署, 主要由原生的go編寫; 
用來兼容接收多種socket  以便支持 tcp,udp, websocket;     
負責橋樑搭建:
第一條:  client->proxy->gate;
第二條: client->proxy->ms service
 
gate: 
網關層; 獨立服務, 支持橫向擴展,主要是進行client-proxy-gate之間的
連接管理;  與所有game進程直連;  也與ms service的網關相連

邏輯層:

game service:
遊戲邏輯服務, 支持橫向擴展; 主要是處理基於有狀態的相關模塊:如戰鬥,技能,副本等;
 
ms service:  
微服務模塊; 抽象出 微服務gate,接收其他服務直連,轉發相關消息至微服務集群;
主要分擔gate的連接壓力,並且分擔邏輯方面game service的相關壓力
處理模塊: 客戶端配置獲取, 簽到, 活動, 小紅點, 郵件, 聊天, 工會, 開關等等此類 無狀態的邏輯;

 

 

 

 

 
world service: 
頂層世界服務模塊; 與幾乎所有的service進行連接;
主要是管理所有的服務,玩家狀態等等; 以及做一些廣播,組播; 也提供熱更的對外接口; 也提供一些簡單的業務邏輯: 諸如全服boss等;  會有slave保證高可用;

數據層:

 

 

 DB service: 
數據層; 主要負責與redis進行直連;  也與mysql進行直連; 
每個game service會定時將data的更新發送到DB service; ms service 則會根據業務情況決定是否直接找DB service進行數據交換還是 找game service進行數據交換;
 
redis: 
採用了哨兵集群模式,開啟 AOF
 
mysql: 
作用有二: 
1: 冷備, 回檔
2: 提供一些簡單的關係型查詢;一般是對實時性不敏感的需求;
 
append data service:    
數據記錄; 主要是追加模式寫數據更新到db的記錄; 便於查檔,歸檔;
 
DB daemon service: 
獨立進程,進行redis的”臟數據”寫入到mysql中,並且寫入成功後追加到append data中;  可以配置 以事務和批量的模式進行寫入;
 
輔助層:
rabbit mq: 
  1. 作為集群的全局隊列用; 
  1. 集群所有service(包括slave)都要定時發送心跳/負載等信息到mq
  1. 微服務會定時消費以上的心跳/負載, 進行負載和進程掛掉的判定, 異常時進行廣播;
  1. 所有服務會訂閱幾個關鍵信息: 擇主, 重連, 主備切換, 負載上限

 

third sdk service: 
第三方sdk服務; 如神策等等:
skynet服務器 –> third sdk service –> 按照json格式寫入log文件 –> 提交給神策後台

————————–————————–————————–————————–————————–————————– 

————————–————————–————————–————————–————————–————————–

————————–————————–————————–————————–————————–————————–

底層核心:

  1. skynet是基於事件的高並發消息處理框架。
  1. 事件主要來源網絡,定時器和信號通知等
  1. 當事件觸發時,skynet將這些事件統一編碼成消息結構,派發給感興趣的服務處理;如果當前無事件,可以做到該服務0的CPU消耗
  1. 核心數據結構是 skynet_context :
  1. 並發解決方案: 消息隊列:每個服務都有一個消息隊列,當隊列中有消息時,會主動掛到全局鏈表。skynet啟動了一定數量的工作線程,不斷從全局鏈表取出消息隊列,派發消息給服務的回調函數去處理。(在 callback 函數調用回工作線程時,消息隊列沒有被放回全局隊列,其它工作線程沒有可能獲得這個 callback 函數所屬服務的消息隊列,所以該服務也就不可能存在並發風險了)