我有一个带socket.io的node.js服务器。我的客户端使用socket.io连接到node.js服务器。
数据以下列方式从客户端传输到服务器:
在客户端
var Data = {'data1':'somedata1', 'data2':'somedata2'};
socket.emit('SendToServer', Data);
在服务器上
socket.on('SendToServer', function(Data) {
for (var key in Data) {
// Do some work with Data[key]
}
});
假设某人修改了他的客户端并向服务器发送了大量数据。例如:
var Data = {'data1':'somedata1', 'data2':'somedata2', ...and so on until he reach for example 'data100000':'data100000'};
socket.emit('SendToServer', Data);
由于服务器上的这个循环......
for (var key in Data) {
// Do some work with Data[key]
}
......服务器需要很长时间来遍历所有这些数据。
那么,防止此类情况的最佳解决方案是什么?
由于
修改
我使用此函数来验证对象:
function ValidateObject(obj) {
var i = 0;
for(var key in obj) {
i++;
if (i > 10) { // object is too big
return false;
}
}
return false;
}
答案 0 :(得分:4)
所以最简单的方法就是在做任何事情之前检查一下数据的大小。
socket.on('someevent', function (data) {
if (JSON.stringify(data).length > 10000) //roughly 10 bytes
return;
console.log('valid data: ' + data);
});
说实话,这有点低效。您的客户端发送消息,socket.io将消息解析为一个对象,然后您获取该事件并将其转换回String。
如果你想要更高效,那么在客户端你应该强制执行最大长度的消息。
为了提高效率(并防止恶意用户),当数据包进入Socket.io时,如果长度太长,那么你应该丢弃它们。你需要想办法扩展原型以做你想做的事情,或者你需要拉动源并自己修改它。此外,我还没有研究过socket.io协议,但我确信你不仅要做“丢弃”数据包。此外,一些数据包是ack-backs和nack-backs,所以你也不想搞砸那些。
附注:如果您只关心密钥的数量,那么您可以使用Object.keys(obj)
返回一组密钥:
if (Object.keys(obj).length > 10)
return;
答案 1 :(得分:3)
您可能会考虑切换到socket.io-stream并直接处理输入流。
这种方式你应该加入块并最终手动解析json输入,但是当输入数据长度超过你决定的阈值时,你有机会关闭连接。
否则(继续使用socket.io方法)在收到整个数据流之前,不会调用您的回调。这并不会阻止你的js主线程执行,但会浪费内存,cpu和带宽。
另一方面,如果您的唯一目标是避免处理算法过载,您可以通过计算接收对象中的元素来继续限制它。例如:
if (Object.keys(data).length > n) return; // Where n is your maximum acceptable number of elements.
// But, anyway, this doesn't control the actual size of each element.
答案 2 :(得分:2)
好吧,我将使用Javascript方面的东西......假设您不希望允许用户超过某个数据限制,您可以这样做:
var allowedSize = 10;
Object.keys(Data).map(function( key, idx ) {
if( idx > allowedSize ) return;
// Do some work with Data[key]
});
这不仅可以让您正确地循环浏览对象的元素,还可以轻松限制。 (显然这也会破坏你自己的预设请求)
答案 3 :(得分:2)
编辑:因为问题是"如何处理服务器过载"您应该使用gninx http://nginx.com/blog/nginx-nodejs-websockets-socketio/检查负载平衡 - 如果一个客户端正在创建瓶颈,您可以拥有其他服务器。其他服务器将可用。即使您解决了这个问题,仍然存在其他问题,例如客户端发送几个小数据包等等。
Socket.io -library似乎有点问题,在websockets层没有管理太大的消息,三年前有一个pull -request,它给出了一个如何解决它的想法:
https://github.com/Automattic/socket.io/issues/886
但是,由于WebSockets -protocol确实具有有限的数据包大小,因此如果已达到某个大小,它将允许您停止处理数据包。执行此操作的最有效方法是在数据包转换为JavaScript堆之前。这意味着您应该手动处理WebSocket转换 - 这是socket.io正在为您做的事情,但它没有考虑数据包的大小。
如果要实现自己的websocket层,使用此WebSocket -node实现可能很有用:
https://github.com/theturtle32/WebSocket-Node
如果您不需要支持旧版浏览器,那么使用此纯网页框 - 方法可能是合适的解决方案。
答案 4 :(得分:1)
也许destroy buffer size
就是您所需要的。
来自wiki:
- 销毁缓冲区大小默认为
10E7
由HTTP传输使用。 Socket.IO服务器将HTTP请求主体缓冲到此限制。此限制不适用于websocket或flashsockets。