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