PipeServer,做一個web/tcp socket轉接器

最近在移植以前的遊戲到微信公眾號上,具體信息可以關注 【寬立遊戲中心】。碰到一個問題是,以前的棋牌遊戲伺服器是用skynet + lua來寫的,用的是tcp socket,現在的公眾號上的遊戲,必須用Html5 + js 來寫,用到的是WebSocket;而WebSocket與tcp socket具體協議並不一樣,不能互通(甚至node.js的websocket server與瀏覽器的websocket client都不能互通?!)。

重新寫一套WebSocket的伺服器?那太麻煩啦!幸好skynet支持httpd/http client,再加上github上也有用skynet做的websocket server實現,於是就寫了一個skynet節點,專門用來從websocket到tcp之間進行轉接,從H5的客戶端收到請求,通過tcp轉發給真正的遊戲伺服器;從tcp里收到真正的遊戲包,再轉發給websocket的h5客戶端。

實現起來不難,很快就完成了。由於需要計數伺服器上有多少人在轉接,卻發現人數對不起來,經常會有-1人出現。後來發現skynet snax服務的一個問題, snax的init 函數是只會調用一次,但exit函數卻有可能調用不止一次(理論上 snax exit只能被調用一次?)。加上標誌變數,exit時只發一次就好啦。

同時也實現了一個tcp 到tcp的轉接。以前的架構里,是客戶端先連接到登錄伺服器,獲取登錄列表和某種遊戲的伺服器列表,再直連到那個遊戲的某個伺服器上。結果之前有段時間被別人DDOS攻擊得生活不能自理(連幾百人的鬥地主伺服器都會被攻擊,還有沒有天理!!!),只能讓客戶連接到別的伺服器,重新開始。現在實現PipeServer轉接tcp和websocket後,任何一個伺服器被攻擊,如果是GameServer被攻擊,由於PipeServer連的是內網,不會影響到用戶;如果是PipeServer被攻擊,重新連接到別的PipeServer就可以再連接回之前的伺服器,可以繼續遊戲了。

本來就應該做這種實現的;實踐證明,架構時偷的懶和腦子裡進的水,遲早會用加班時流的汗來補回。

比較一下 內網tcp socket和節點之間rpc的效率,由於節點之間rpc應該用的也是內網的tcp,效率上應該沒有本質上的區別;但是用節點的rpc,一個是方便,另一個是有epoll統一管理,實現起來比較簡潔;用內網tcp,好處是不會因為升級代碼破壞rpc的兼容性,升級更加平滑,這個對伺服器經常性更新調整很方便。

附:github上的skynet websocket 是這個: Skycrab/skynet_websocket
推薦閱讀:

伺服器端編程心得(一)—— 主線程與工作線程的分工
伺服器端編程心得(七)——開源一款即時通訊軟體的源碼
深挖NUMA
loki的基礎服務——timer
伺服器端編程心得(二)—— Reactor模式

TAG:遊戲伺服器 | 伺服器架構 | 棋牌遊戲 |