Socket.IO服务器限制快速客户端

时间:2013-02-20 23:35:49

标签: node.js socket.io

我有一台使用socket.io的服务器,我需要一种限制发送服务器数据的客户端的方法。服务器公开TCP接口和socket.io接口 - 与TCP服务器(来自net模块)我可以使用socket.pause()socket.resume(),这有效地限制了客户端。但是对于socket.io的socket类,没有pause()resume()方法。

向客户提供反馈服务器并且需要减速的最简单方法是什么?我喜欢socket.pause()socket.resume(),因为它在客户端不需要任何额外的代码 - 备份TCP套接字并且事情自然会变慢。 socket.io的任何等价物?

更新:我提供了一个与服务器交互的API(目前有一个运行在TCP上的python版本和一个使用socket.io的JavaScript版本)。所以我对客户端的功能没有任何真正的控制权。这就是使用socket.pause()socket.resume()这么好的原因 - 备份TCP流会降低python客户端的速度,无论它尝试做什么。我正在寻找一个JavaScript客户端的等价物。

6 个答案:

答案 0 :(得分:3)

通过足够的挖掘我发现了这个:

this.manager.transports[this.id].socket.pause();

this.manager.transports[this.id].socket.resume();

当然,如果socket.io连接不是Web套接字连接,并且可能在将来的更新中中断,这可能不起作用,但是现在我将继续使用它。当我将来得到一些时间时,我可能会将其改为Pascal提出的QUOTA_EXCEEDED解决方案。

答案 1 :(得分:2)

这是实现限制的一种肮脏方式。虽然这是一个老帖子;有些人可能从中受益:

首先注册一个中间件:

io.on("connection", function (socket) {

 socket.use(function (packet, next) {
    if (throttler.canBeServed(socket, packet)) {
        next();
    }
 });
 //You other code ..
});

canBeServed是一个简单的节流器,如下所示:

function canBeServed(socket, packet) {
 if (socket.markedForDisconnect) {
     return false;
 }

 var previous = socket.lastAccess;
 var now = Date.now();
 if (previous) {
    var diff = now - previous;

    //Check diff and disconnect if needed.
    if (diff < 50) {
        socket.markedForDisconnect = true;
        setTimeout(function () {
            socket.disconnect(true);
        }, 1000);
        return false;
    }
}

socket.lastAccess = now;

return true;
}

您可以使用process.hrtime()而不是Date.time()。

答案 2 :(得分:1)

看起来你应该放慢你的客户的速度。如果一个客户端发送的速度太快,服务器无法跟上,那么对于100个客户端来说这不会很好。

执行此操作的一种方法是让客户端在发出其他任何内容之前等待每个发出的回复。这样,服务器可以通过仅在准备好时回答,或者仅在设定的时间之后回答来控制客户端发送的速度。

如果这还不够,当客户端超过每秒x次请求时,开始回复QUOTA_EXCEEDED错误,并忽略他们发送的数据。这将迫使外部开发人员使他们的应用程序按照您希望的方式运行

答案 3 :(得分:1)

如果您的服务器上有回调,通常会将响应发送回您的客户端,您可以尝试更改它:

之前:

  var respond = function (res, callback) {
    res.send(data);
  };

var respond = function (res, callback) {
    setTimeout(function(){
        res.send(data);
      }, 500); // or whatever delay you want.
  };

答案 4 :(得分:0)

作为另一个建议,我建议这样的解决方案: MySQL通常会收到大量请求,这些请求需要的时间比请求的速率要长。 服务器可以在db中的表中记录请求,假设此操作对于请求进入的速率足够快,然后以正常速率处理队列以使服务器维持。此缓冲系统将允许服务器运行缓慢但仍处理所有请求。

但是如果你想要顺序的东西,那么应该在客户端发送另一个请求之前验证请求回调。在这种情况下,应该有一个服务器就绪标志。如果客户端在标志仍为红色时发送请求,则可能会有消息告知客户端速度变慢。

答案 5 :(得分:0)

只需将您的客户端发射器包装成如下所示的函数

let emit_live_users = throttle(function () {
    socket.emit("event", "some_data");
}, 2000);

使用像下面这样的节流功能

function throttle(fn, threshold) {
    threshold = threshold || 250;
    var last, deferTimer;

    return function() {
        var now = +new Date, args = arguments;
        if(last && now < last + threshold) {
            clearTimeout(deferTimer);
            deferTimer = setTimeout(function() {
                last = now;
                fn.apply(this, args);
            }, threshold);
        } else {
            last = now;
            fn.apply(this, args);
        }
    }
}