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.和其他Node贡献者。 ^ RangeError:超出最大调用堆栈大小

我知道没有足够的可用堆栈空间,所以发生exception,并且进程终止,但即使我用–stack-sizevariables放大堆栈,这也不能解决问题,因为我总是可以生成更多连接,最终会终止服务器。

我的问题是:我怎样才能防止这一点。 这是一个有效的拒绝服务(DoS)场景,任何人都可以将这个小脚本绑在一起,强制节点服务器终止,但是我想阻止这种情况的发生。 我想节点服务器永远不会终止,只是缓慢地处理消息。

任何想法,如果这可以被阻止。 我不确定我是否想阻止IP,因为我也想让手机login系统,其中很多人使用相同的IP,所以节点服务器可能会误认为DoS正在到位移动networking运营并阻止其IP。

谢谢

如果你想让你的节点服务器永远运行,无论如何,使用https://github.com/nodejitsu/forever

至于例外 – 我的预感是var sub = redis.createClient('127.0.0.1', 6379); 可以在每次build立连接时在堆栈中分配一个variables。

我将首先尝试将var subs = []放在全局作用域中, subs[socket.id] = redis.createClient('127.0.0.1', 6379);

或者像socket.sub = redis.createClient('127.0.0.1', 6379); 捎带现有的,希望基于堆的socket.io数据结构。

如果不工作,请尝试通过删除使用Redis来隔离问题。