分享下我之前做的服務器框架; 游戲在線最高3萬; 物理機I7的3台阿里雲分服;性能及其強勁;
框架: 底層基於比較流行的skynet,基礎采用c語言,腳本lua,部分服務golang;
Skynet: 是一個基於C跟lua的開源服務端並發框架,這個框架是單進程多線程Actor模型。所以他對於機器的性能壓榨是很高的。
- proxy支持tcp,udp,websocket(支持http和https)
特點:
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:
- 集群所有service(包括slave)都要定時發送心跳/負載等信息到mq
- 微服務會定時消費以上的心跳/負載, 進行負載和進程掛掉的判定, 異常時進行廣播;
- 所有服務會訂閱幾個關鍵信息: 擇主, 重連, 主備切換, 負載上限
third sdk service:
第三方sdk服務; 如神策等等:
skynet服務器 --> third sdk service --> 按照json格式寫入log文件 --> 提交給神策后台
------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------
底層核心:

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