nodejs-tw / ama

Ask me anything!
MIT License
31 stars 1 forks source link

nodejs作為server在超過24人連線時同步會產生延遲 #35

Open z20818z opened 4 years ago

z20818z commented 4 years ago

感謝使用 Node.js Taiwan AMA,以下附上簡單提問範例供參考,請把內容改成你自己遇到的問題

目的

<<我希望做一個 多人上線的遊戲伺服器 ,達成即時同步的效果>>

使用的工具

<<我在 Windows 下使用 npm 安裝 node.js 10.16 >>

操作流程

<<我下了 node dive_server.js 運行>>

遇到的問題

<<少人連線的時候不會出現延遲,但是在超過24人連線之後她會出現延遲的現象>>

嘗試過的解法

<<我嘗試過把 變數減少,但是在運行超過28台主機的時候便會出現延遲>>

程式碼

data_object.js

this.server_update = function(id,value){                             
       socket.emit('update_data',{  
                      'room_id':self.room_id, 
             'player_data':id,
             'get_value':value,
                 'get_number':value_object['player_num']});    
    }

dive_server.js

var express = require("express");
var app = express();
var http = require('http').Server(app);
var io = require('socket.io')(http,{
  pingInterval: 1000,
  pingTimeout: 2000
});
var mysql = require('mysql');

var con;
var db_config = {
  host: "localhost",
  user: "root",
  password: "",
  post:'3306'
};
app.use(express.static('public'));                        
  socket.on('update_data',function(data){
         Object.keys(data).forEach(function(key) {  // 逐行列出標頭
           switch(key){
            case 'join_room':
              socket.join(data.room_id);               //連線時候4人順便將它設定群組
              socket.join(data.join_same_team);             //同對1房間
              break;
            case 'player_data':
              var attr_data = { 'id':data['player_data'],
                                'value':data['get_value']};                            
              io.to(data.room_id).emit('other_player_change', attr_data);             //將資訊傳給其他連線者的的IO
              break;
            case 'player_data_only':         //不傳給自己
              var attr_data = { 'id':data['player_data_only'],
                                'value':data['get_value']};                            
              socket.broadcast.to(data.room_id).emit('other_player_change', attr_data);             //將資訊傳給其他連線者的的IO
              break;
            case 'same_team':
              var attr_data = { 'id':data['same_team_id'],
                                'value':data['get_value'],
                        'another_value':data['another_value']};                                
              io.to(data.same_team).emit('other_player_change', attr_data);             //將資訊傳給同隊友
              io.to(data.another_team).emit('other_player_change', { 'id':data['same_team_id'],'value':data['another_value']});//將資訊傳給另外一隊同隊友
              break;
            case 'team_msg':
              var attr_data = {'msg':data.msg,
                                'nickname':data.nickname,
                        'index':data.index};    
              io.to(data.team_msg).emit('team_msg', attr_data);             //將資訊傳給同隊友
              break;
            case 'same_team_game_over':
                var attr_data = { 'dead':data['dead']};                                
                io.to(data.room_id).emit('game_over_msg', attr_data);             //將資訊傳給其他連線者的dive的IO
                break;
            }

          })
  });

html js

var pass = player_one_value[1];   // 裡面有十幾個變數

for(var e = 0;e<pass.length;e++){
    var value = diveLinker.getAttr(pass[e]);
    if(data_array[e] != value){
        project_data.server_update_only(pass[e],value);
    }else{
        data_array[e] = value;
     } 
}
fillano commented 4 years ago
  1. 請量化問題,例如所謂的延遲,是延遲多少,在多少連線時,會有多少的延遲等
  2. 你怎麼測試這些連線的?用28台不同機器打一台伺服器?
  3. 有監看CPU跟記憶體使用的狀況嗎?
  4. 可以用Profiling工具來找可能的瓶頸點,例如clinic.js等,請google一下
z20818z commented 4 years ago
  1. 請量化問題,例如所謂的延遲,是延遲多少,在多少連線時,會有多少的延遲等
  2. 你怎麼測試這些連線的?用28台不同機器打一台伺服器?
  3. 有監看CPU跟記憶體使用的狀況嗎?
  4. 可以用Profiling工具來找可能的瓶頸點,例如clinic.js等,請google一下

1.延遲是latency會在24人連線後數據同步時有100-200不等的延遲 28之後會開始飆升至1000 甚至更高 2.我開了28台電腦連線到server上面進行遊戲 3.cpu使用率在50%以下 記憶體使用率為50%左右 4.我這幾天嘗試看看 目前的想法是 可能是js裡面的for迴圈在每一個frame進行同步所以造成socket堵塞?

fillano commented 4 years ago

一個寫法的建議: 可以考慮切出更多的on(event, data=>{})之類,讓他可以更快處理完,這樣雖然程式看起來比較複雜,但是比較不會擋到event loop,使得latency比較快速累積。畢竟不管多少連線,都是共用一個event loop,只用一個update_data事件來處理所有的資料,可能會比較慢。

不過還是用Profiling的方式來確定問題會比較準。

poying commented 4 years ago

cpu 使用率看起來不高,可以用 cluster module(mp2 的 cluster mode)來提高 cpu 使用率。用 cluster module 時,socket.io 的應該會需要用 redis adapter。

clonn commented 4 years ago

看起來慢的地方會在 js html 的部分, 這樣的寫法會造成越多人進來就算不是在同一個 group 裡面,但還是會不斷的收到所有訊息和資訊。

推測是因為用了 for loop 來處理前端資料,建議是拆開成不同 event listener 來處理,請愛用 event-driven 慢的感覺應該是前端感覺慢,並非伺服器的部分

Po-Ying Chen notifications@github.com 於 2020年1月5日 週日 下午6:45寫道:

cpu 使用率看起來不高,可以用 cluster module(mp2 的 cluster mode)來提高 cpu 使用率。用 cluster module 時,socket.io 的應該會需要用 redis adapter。

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/nodejs-tw/ama/issues/35?email_source=notifications&email_token=AACU5HYWY3HN3P6F6Q5G4BLQ4G225A5CNFSM4KCLBYF2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEIDTUVA#issuecomment-570899028, or unsubscribe https://github.com/notifications/unsubscribe-auth/AACU5H22MWS7L2TAFV6IRMLQ4G225ANCNFSM4KCLBYFQ .

--

Caesar Chi.

Traveler and web developer. Focus on open source group, member of Node.JS Taiwan Community.

About me, http://about.me/clonn