2013-01-09 66 views
2

我已經寫了一個小型的Socket.IO服務器,它工作正常,我可以連接到它,我可以發送/接收消息,所以一切正常。您只需將代碼的相關部分在這裏提出:Socket.IO超出最大調用堆棧大小

var RedisStore = require('socket.io/lib/stores/redis'); 
const pub = redis.createClient('127.0.0.1', 6379); 
const sub = redis.createClient('127.0.0.1', 6379); 
const store = redis.createClient('127.0.0.1', 6379); 

io.configure(function() { 
    io.set('store', new RedisStore({ 
    redisPub : pub, 
    redisSub : sub, 
    redisClient : store 
    })); 
}); 

io.sockets.on('connection', function(socket) { 
socket.on('message', function(msg) { 
    pub.publish("lobby", msg); 
    }); 


    /* 
    * Subscribe to the lobby and receive messages. 
    */ 
    var sub = redis.createClient('127.0.0.1', 6379); 
    sub.subscribe("lobby"); 
    sub.on('message', function(channel, msg) { 
    socket.send(msg); 
    }); 
}); 

我也寫下面給出連接到在setInterval函數,它產生一個新連接的每個10milisecons服務器和產卵連接的腳本,所以它的產生了相當多的連接。

#!/usr/bin/env node 

var io = require('socket.io-client'); 
var reconn = {'force new connection': true}; 
var sockets = []; 

var num = 1000; 

function startSocket(i) { 
    sockets[i] = io.connect("http://127.0.0.1:8080", reconn); 
    sockets[i].on('connect', function() { 
    console.log("Socket["+i+"] connected."); 
    }); 
    sockets[i].on('message', function(msg) { 
    console.log("Socket["+i+"] Message received: "+msg); 
    }); 
} 



/* 
* Start number of sockets. 
*/ 
for(var i=0; i<num; i++) { 
    startSocket(i); 
} 



/* 
* Send messages forever. 
*/ 
setInterval(function() { 
    for(var i=0; i<num; i++) { 
     sockets[i].send("Hello from socket "+i+"."); 
    } 
}, 10); 

這個腳本是一個基準測試工具產卵1000個到服務器的連接,但幾分鐘運行時,服務器會出現以下錯誤信息死亡:

node.js:0 // Copyright Joyent, Inc. and other Node contributors.^ RangeError: Maximum call stack size exceeded

我知道,有沒有足夠的堆棧可用的空間以便發生異常並且進程終止,但即使我用--stack-size變量放大堆棧,這實際上也不能解決問題,因爲我總是可以產生更多的連接,最終會終止服務器。

我的問題是:如何防止這種情況。這是一個有效的DoS方案,任何人都可以將這個小腳本一起破解並強制節點服務器終止,但是我想阻止這種情況發生。我希望Node服務器永遠不會終止,只是緩慢地處理消息。

任何想法,如果這可以被阻止。我不確定我是否想要阻止IP,因爲我還希望手機能夠登錄到系統,其中很多人使用相同的IP,因此節點服務器可能會錯誤地認爲DoS正在到位移動網絡運營並阻止其IP。

謝謝

+0

一個快速和骯髒的解決辦法是躲在一個代理/負載均衡器 – JeffS

回答

0

如果您想您的節點服務器一直運行下去,不管是什麼,使用https://github.com/nodejitsu/forever

至於例外 - 我的預感是var sub = redis.createClient('127.0.0.1', 6379);可以在每次堆棧分配的變量建立連接。

我先試試把var subs = []在全球範圍內和 subs[socket.id] = redis.createClient('127.0.0.1', 6379);

或者類似的東西socket.sub = redis.createClient('127.0.0.1', 6379);捎帶現有的,希望基於堆的,socket.io數據結構。

如果不工作,通過刪除使用Redis的的隔離問題...

+0

服務器有用嗎?請驗證 – whadar

相關問題