2012-11-24 41 views
1

昨天晚上我們爲我們的一個活動設置了現場報價,我們遇到了seriouse性能問題。 Socket.io無法爲超過400至500個客戶端連接的socket.io.js提供服務。該代碼非常簡單,每隔幾分鐘只有一條消息被廣播給所有的客戶端,所以我認爲代碼中沒有太多的改進空間。服務器的硬件並不是最好的,但我們在代碼的正常運行時間內監視這些進程,並且他們都沒有引起問題。Socket.io性能問題

你有任何想法如何解決這個問題,或者至少還有什麼可能是它的原因。它看起來像socket.io只是掙扎,但不是由於缺乏硬件能力。

服務器結構

var io = require('socket.io').listen(443); 
io.set('log level', 9); 

//SQL CONNECTION 

io.sockets.on('connection', function (socket) { 

var sql_items = 'SELECT * FROM entries ORDER BY tstamp DESC'; 

db_query(sql_items , function(res_items) { 
    socket.emit('init', res_items); 
});  
socket.on('new_entry', function (data) { 
     //SECURE 
    if(!checkedSocketUsers[socket.id]) return false; 

    var currentTime = new Date(); 

    if(currentTime.getMinutes() < 10); 

    var minutes = currentTime.getMinutes(); 
    if(minutes < 10) minutes = "0" + minutes; 

    var hours = currentTime.getHours(); 
    if(hours < 10) hours = "0" + hours; 

    var tstamp = currentTime.getTime()/1000; 

    var time = hours + ":" + minutes; 

    sqli = "INSERT INTO entries (uid, tstamp, text, type) VALUES (null, "+tstamp+", '"+data.text+"', '"+data.type+"')"; 
    client.query(sqli, function(err, info) { 

     var br_data = {}; 

     br_data.time = time; 
     br_data.text = data.text; 
     br_data.uid = info.insertId; 
     br_data.type = data.type; 

     socket.broadcast.emit('broadcast_entry', br_data); 
     socket.emit('broadcast_entry', br_data); 
    }); 
}); 

socket.on('update_entry', function(data) { 
    //SECURE 
    if(!checkedSocketUsers[socket.id]) return false; 

    sqlu = "UPDATE entries SET text = '"+data.text+"' WHERE uid = "+data.uid; 

    client.query(sqlu, function(err, info) { 

     br_data = data; 

     socket.broadcast.emit('broadcast_update_entry', br_data); 
    }); 
}); 

socket.on('remove_entry', function(data) { 
    //SECURE 
    if(!checkedSocketUsers[socket.id]) return false; 

    var uid = data.uid; 

    sqld = "DELETE FROM entries WHERE uid = "+uid; 
    client.query(sqld, function(err, info) { 
     var br_data = {}; 

     br_data.uid = uid; 

     socket.broadcast.emit('broadcast_remove_entry', br_data); 
     socket.emit('broadcast_remove_entry', br_data); 
    }); 
}); 
}); 

客戶結構

socket = io.connect("http://localhost:443");  

socket.on('init', function(data) { 
//DOM Manipulation 
}); 

socket.on('broadcast_entry', function(data) { 
//DOM Manipulation 
}); 

socket.on('broadcast_remove_entry', function(data) { 
//DOM Manipulation 
}); 

socket.on('broadcast_update_entry', function(data) { 
//DOM Manipulation 
}); 
+1

您運行的是什麼操作系統?您在操作系統中設置了允許的套接字/文件數量打開的限制嗎? –

+1

很難知道,因爲你沒有提供任何可能阻塞或瓶頸的代碼。 :( –

+0

我同意,從您提供的代碼來看,沒有瓶頸,因爲這些只是簡單的發射和廣播從socketIO發出,性能非常高。 – toxicate20

回答

4

這是一個有點分不清什麼瓶頸你打。有幾種可能性供您探索:

您可能已達到您的進程中打開的文件句柄的數量限制。您的Linux內核是使用每個進程配置的最大數量的文件句柄編譯的(套接字連接使用文件句柄)。您可以通過運行「ulimit -a」來查看(最大)打開文件限制。您可以在運行流程之前增加此數字,只需google「ulimit打開的文件」即可。

另一個想法......您在任何特定時間最多可以有多少條消息?你正在做一個數據庫查詢來爲每個新的連接檢索所有這些。因此,如果連接數量急劇增加,您可能只是爲了加載最初的列表而做很多查詢。作爲一個實驗,您無法在「連接」查詢上進行初始化,以查看縮放比例如何提高。如果這有很大幫助,那麼您可以輕鬆地將查詢結果緩存在JavaScript變量中,而不是針對每個連接訪問數據庫。

一些有趣的閱讀...

http://drewww.github.com/socket.io-benchmarking/

+0

Thx爲您的答案。我不認爲它可能來自查詢,因爲這是唯一的運行在數據庫服務器和400-500連接(只有一小部分在同一時間重新連接)並不多,而且在db中不超過50個條目。 但我會分析你提到的一切。 –