我已經寫了一個小型的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。
謝謝
一個快速和骯髒的解決辦法是躲在一個代理/負載均衡器 – JeffS