Node.js之網遊服務器實踐

此文已由做者堯飄海受權網易雲社區發佈。
web

歡迎訪問網易雲社區,瞭解更多網易技術產品運營經驗。編程


隨着Node.js的不斷髮展與壯大,應用範圍也愈來愈普遍,從傳統的企業應用,到互聯網使用,再到雲計算的發展,它的身影也是隨處可見。固然,它的受歡迎程度能在短期內獲得這麼快的發展,除卻與其自己的事件模型及V8的性能優化等一系列特性有關以外,還和國內外不少互聯網公司的攻城師的大量應用和參與到開源項目中有密切關係,如網易的遊戲開發,淘寶的數據之美等等。隨着HTML5應用和移動互聯網平臺的指數增加,愈來愈多的用戶使用了移動平臺的休閒服務,採用 Node.js 實現高性能和可擴展性的遊戲服務將是一件有意義的工做。緩存

在互聯網上,目前有一些採用 Node.js 實現的開源遊戲服務框架,如 Mozilla Browser Quest Google Grits Chilly等。可是無一例外,這些框架不但與遊戲邏輯聯繫緊密,並且幾乎沒有可擴展性和性能數據,同時也不提供任何遊戲開發的管理工具,除了採用 JavaScript 編寫外,很難體現出採用 Node.js 實現遊戲開發的優越性。安全

概念

一般遊戲分爲角色扮演類和策略類及混合類等幾種遊戲類型。那麼在網頁遊戲類型中,根據遊戲的類型,開發者可能採用不一樣的架構實現方式,如策略類遊戲可能更偏重於遊戲的策略性和邏輯性,也就是考驗遊戲玩家的各類組合或搭配之類的遊戲,對實時性的要求不會很高,在用戶的可接受範圍以內便可,所以也能夠採用經常使用的Web應用開發模式來實現,而客戶端採用輪詢或長鏈接等方式來實現,這些應用模式也有不少的相關經驗能夠參考,所以能作到具備較好的可擴展性及伸縮性;此外,應用服務器和服務框架等也能夠採用現存的技術實現,可是這隻能知足對遊戲實時性要求不高的場景服務,因爲此類的應用方案很是成熟,在下文的討論中,將再也不詳述。性能優化

角色扮演類遊戲根據策劃的要求能夠實現各類各樣的功能,如聊天,打鬥,自動刷怪等各類複雜的功能,可是開發者基本能夠把這些功能抽象地劃分爲二大類,即服務端的網絡傳輸與邏輯運算能力,這樣遊戲服務的開發和實現會稍微簡單些。如今,網絡的實時傳輸基本上是採用Socket服務器來實現的,邏輯運算這個就不須要再述了,所以,遊戲服務器就能夠粗略的概括爲Socket的服務器綜合遊戲業務邏輯的實現。服務器

Web應用區別

從上面遊戲服務的概念簡單介紹中能夠得知,實時遊戲服務器的開發與傳統的Web開發仍是具備一些不一樣點,這些不一樣點着重體如今如下幾個方面:
大部分的Web應用仍是短鏈接的方式去實現,而遊戲的實時性須要採用長鏈接的方式進行。websocket

Web應用的場景通常是讀多寫少的應用,熱點數據基本能夠緩存;遊戲服務的數據常常發生變更,如移動中的路徑,打怪掉血等,緩存基本很快就失效,屬於寫多讀少的應用場景。網絡

廣播特性,即Web應用行爲上基本只須要用戶與服務器交互,其餘用戶要實現共享他人信息的時候,會採用相似拉的方式如長輪詢來實現數據交互,即便在沒有數據更新的狀態時也須要消耗必定的服務端資源,形成必定的浪費;遊戲裏面的交互方式須要實時進行,對影響三方的數據,必須採用廣播的方法進行消息推送,即推的模式。架構

目前的Web應用開發通常採用無狀態性的方式來實現,所以能夠實現較好的可擴展性,不少Web服務會採用綁定會話或集中會話等方式工做,當後面的某臺服務器出現宕機時,服務也能夠很快的切換;可是遊戲服務器和用戶之間的鏈接是有狀態的,在斷開時須要進行相關的通知和數據持久化,在重連時須要進行狀態恢復等手段來維護遊戲世界的運行。app

除以上幾點不一樣以外,還有負載均衡的策略,服務驅動方式,系統斷定,系統安全如外掛做弊等相關問題,文章中再也不對他們進行對比說明。通常來說,根據遊戲的規模與需求,一般遊戲服務器的實現的模式會使用以下的三種架構方式來實現。

單進程服務架構

1 單進程服務架構

1是目前互聯網上的不少遊戲服務器使用的架構,好比商用的SmartFoxServer遊戲服務器,開源的有Google Grits, Mozilla Browser Quest等框架。全部的程序在同一個進程裏面運行,架構簡單,開發人員上手快,開發和調試很是方便又快速,成本較低,後期的維護成本可能隨着遊戲項目的大小而不一樣,可是總體應該不會過高。很明顯,遊戲的世界是在同一個進程裏運行,在單個場景都有很多在線用戶的時候,若是採用單進程的 Node.js 實現的話,每一個用戶的操做可能會有必定的延遲,特別是在大量用戶同時作大量操做與AI運算時,如服務端尋路和自動殺怪,延遲會更加嚴重;同時單進程對計算機資源使用有限。所以只適合遊戲的原型製做或小型的遊戲開發。另外,因爲遊戲的狀態與複雜性,也沒法較好的實現遊戲的可擴展性,基本只能經過添加遊戲服務器的方式來實現,即所謂的開新服,而這些用戶之間是沒法在同一個世界裏通訊會話和交互的。儘管Node.js支持原生的TCP服務,使用簡單;可是目前大部分網絡應用中,尤爲是支持HTML5的應用,socket.io因爲性能較好而且使用簡單,成爲大部分應用採用的網絡庫來實現高性能websocket服務。在移動互聯網應用中,因爲協議較複雜與通訊數據等問題,須要必定的裁減。下面示例中,就是最簡單的單進程服務的原型:

var socketio =
require('socket.io');
var io =
socketio.listen(8080);
io.sockets.on('connection',function(socket){
     socket.on('disconnect',function(){
     //user leave
     });
 socket.on('message',function(msg){
     if (getLoginStatus(socket)) {
    game[data.action].apply(null,[socket,msg]); 
     } else {
     game['login'].apply(null,[socket,msg]); 
     }
 });
});


多進程服務架構

2 多進程服務架構

在上圖2中,咱們能夠看出,每一個進程負責採用單一職責,各進程間經過必定的規則(如RPC遠程過程調用)來進行通訊,遊戲中的各場景服務使用一個進程來服務,實現各場景遊戲運行的分離。可是在開發過程當中,不須要考慮每一個場景具體的信息,所有采用統一的代碼來實現,開發方便,經過添加適當的參數來實現較易的調試,每一個進程分別運行在服務器的多核上,便可以充分使用計算機的資源,也因爲職責單一,因爲每一個進程都專職作本身的事,所以,在壓力大的時候,能夠很明顯的查出問題所在,並能夠較好的實現對相應的服務進行調優,能夠達到較好的性能和必定的可伸縮性。可是,在各遊戲的世界裏,沒法準確的知道遊戲的狀態如在線人數之類的,會存在熱點數據和服務過載等一些問題,形成部分服務堵死等現象,也沒法達到在不停服務的狀況下進行服務器擴容與自動切換等問題,同時會給遊戲運營帶來必定的問題,不能充分的對玩家數據進行分析與挖掘,所以,這種實現方式能夠知足中小型的遊戲開發。這種架構目前不少的遊戲服務器中還在使用,技術發展也較成熟,如傳奇服務端架構等。

分佈式服務架構

3 分佈式的服務架構

一樣,分佈式的服務架構與多進程的架構具備不少相同點,如進程服務單一職責,較好的性能調優,同時採用集中式的方式對遊戲服務器進行管理,各遊戲服務器能夠經過自定義的方式即DSL進行遊戲業務的路由與分發,經過主備服務器的狀態能夠很清楚的知道每一個服務的狀態及運行狀況,這樣可經過動態添加服務來到達負載均衡,具有較好的性能和可擴展性,能知足大型遊戲的開發。固然,採用這樣方式,會具備必定的複雜性,同時各服務之間多是不在同一臺服務器上的,所以會帶來必定的網絡開銷,在大量廣播的場景中,網絡IO壓力大,須要經過定時批量或AOI服務等方式來進行廣播通訊,同時,遊戲的通訊協議須要通過特別的設計,儘可能避免數據序列化上的CPU重複開銷,採用胖客戶端的方式去分擔遊戲服務器的序列化與反序列化;另外還有可能引入分佈式事務等相關問題,須要在一個集中點進行處理。固然,在遊戲設計中,策劃開發人員須要儘可能避免這種跨場景跨進程的遊戲邏輯需求。

在分佈式架構實現中,目前商業上較成功的案例是BigWorld遊戲服務框架,國內外不少大型的遊戲開發商都在使用。而在開源部分,目前尚未較穩定成熟的方案,咱們團隊採用Node.js正在開發的Pomelo遊戲服務框架正在努力實現這一目標,現已進入最後的文檔整理階段,預計將在十月份進行開源與線上示例演示。

總結

<span style="display: inline !important; float: none; background-color: transparent; color: rgb(51,

相關文章:
【推薦】 秋讀|10本熱門圖書(人工智能、編程開發、架構、區塊鏈等)免費送!

相關文章
相關標籤/搜索