游戲服務器骨架:gonet2
gonet/2是新一代游戲服務器骨架,基于go語言開發,采用了先進的http/2作為服務器端主要通信協議,以microservice作為主要思想進行架構,采用docker作為服務發布手段。相比第一代gonet,基礎技術選型更加先進,結構更加清晰易讀可擴展。
相關文檔
- ROADMAP.md -- 開發計劃
- TOOLCHAIN.md -- 工具鏈
- INSTALL.md -- 安裝
為什么用microservice架構?
業務分離是游戲服務器架構的基本思路,通過職能劃分,能夠更加合理的調配服務器資源。資源的大分類包括,IO,CPU,MEM,BANDWIDTH, 例如常見的情景:
IO: 如: 數據庫,文件服務,消耗大量讀寫 CPU: 如: 游戲邏輯,消耗大量指令 MEM: 如: 分詞,排名,pubsub, 消耗大量內存 BANDWIDTH: 內網帶寬高,外網帶寬低,物理上越接近的,傳輸速度越高
玩家對每種服務的請求量有巨大的不同,比如邏輯請求100次,分詞請求1次,所以,沒有必要1:1配置資源,通過microservice方式分離服務,可以根據業務使用情況,按需配置服務器資源。當服務容量增長,如果在monolithic的架構上做,即全部服務揉在一起成一個大進程,會嚴重浪費資源,比如大量內存被極少被使用的模塊占用, 更嚴重的問題是,單臺服務器的資源不是無限制的,雖然目前頂級配置的服務器可以安裝高達96GB的內存,但也極其昂貴,部署量大的時候,產生的費用也不容小覷。
為什么選HTTP/2?
為了把所有的服務串起來,必須滿足的條件有:
1. 支持一元RPC調用 (一般的請求/應答模式,類似于函數調用)
2. 支持服務器推送(例如pubsub服務,異步通知)
3. 支持雙向流傳遞 (網關透傳設備數據包到后端,后端應答數據經過網關返回到設備)
我們暫不想自己設計RPC,一是目前RPC繁多,沒必要重新發明輪子,二是作為開源項目,應充分融入社區,利用現有資源。我們發現目前http/2(rfc7540)滿足以上所有條件,google推出的gRPC就是一個基于http/2的RPC實現,當前架構中,所有的服務(microservice)全部通過gRPC連接在一起。 http/2支持stream multiplex,即可以在同一條TCP連接上,傳輸多個stream(1:N),stream概念能夠非常直觀的1:1映射玩家雙向數據流。
附: HTTP/2 幀封裝
+-----------------------------------------------+ | Length (24) | +---------------+---------------+---------------+ | Type (8) | Flags (8) | +-+-------------+---------------+-------------------------------+ |R| Stream Identifier (31) | +=+=============================================================+ | Frame Payload (0...) ... +---------------------------------------------------------------+ Figure 1: Frame Layout
基本服務模型
+ | +--------------> auth | +----> game1 | agent1+------> | +----> game2 | + agent2+------> +-----> snowflake | | +----> game3+----> | | | +-----> chat ++ | +-----> rank +
使用方式假定為:
- 前端用兩個部署在不同物理服務器上的agent服務接入,無狀態,客戶端隨機訪問任意一臺agent接入,比如使用DNS round-robin方式連接。
- agent和auth配合處理完鑒權等工作后,數據包透傳進入game進行邏輯處理。如果有多臺game服務器,那么用戶需要指定一個映射關系(userid->server_id),用來將玩家固定聯入某臺game服務器。
- game和各個獨立service通信,配合處理邏輯。service如果是無狀態的,默認采用round-robin方式請求服務,如果是帶狀態的,則根據標識聯入指定服務器。
具體的服務描述以及使用案例,請進入各個目錄中閱讀。
所有服務都依賴的一個基礎服務是nsqd,用來做分布式日志收集,所有的服務會把日志發送到本地的nsqd,通過nsqlookupd管理nsqd拓撲,通過tailn工具或nsq_tail,可以集中收集格式化的日志(json)數據,消息主題為LOG。
游戲中的歸檔日志(REDOLOG),也會通過nsqd發布,并通過arch服務自動歸檔,消息主題為REDOLOG。
nsqd部署的方式為: 每個服務器實例部署一個
實際項目中怎么使用gonet/2?
clone下來慢慢改,不提供插件接口式的可升級模塊,gonet/2只提供關鍵通路和demo,我不想做一個侵入式的骨架,只想在架構層面提供一個我認為比較優秀的思路并在此基礎上努力做到整體最優。
游戲模塊
進入每個服務閱讀對應文檔
1. agent: 網關
2. game: 游戲邏輯
3. snowflake: UUID發生器
4. chat: 聊天服務
5. auth: 鑒權,登陸環節
6. libs: 公共組件包
7. rank: 排名服務
8. geoip: IP歸屬查詢
9. arch: 歸檔服務
10. bgsave: 與redis結合的存檔服務
11. wordfilter: 臟詞過濾服務
基礎設施
術語:
- coordinator -- zk, etcd這種分布式一致性服務
- message backbone -- 服務器件消息總線,通常為pub/sub模式,數據密集
實現:
基礎設施是用于支撐整個架構的基石,選擇nsq, etcd的理由是:
- 全部采用go實現,技術棧統一
- nsq在bitly商用效果很好,能支持大規模的,高可用(特別是發生網絡分區)的分布式應用
- etcd是coreos出品的coordinator, 已經得到大面積的使用,有成功案例,配套完善。
社區
QQ群: 459420581
鏈接
- gonet/2 unity 客戶端網絡庫 -- by ycs
- Gonet2游戲服務器框架解析 -- by 高
- grpc,nsq等源碼分析 -- by tenywen
- Protobuf安裝 -- by __IveCode
PS. 感謝熱心網友對源碼的解讀
資料
- protobuf: https://github.com/google/protobuf
- protobuf golang plugin: https://github.com/golang/protobuf
- grpc: http://grpc.io
- http/2: http://http2.github.io/