4

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

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

更新:我提供了一个与服务器交互的 API(目前有一个通过 TCP 运行的 python 版本和一个使用 socket.io 的 JavaScript 版本)。所以我对客户的行为没有任何真正的控制权。这就是为什么使用socket.pause()andsocket.resume()非常棒的原因——无论它试图做什么,备份 TCP 流都会减慢 Python 客户端的速度。我正在寻找 JavaScript 客户端的等价物。

4

6 回答 6

3

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

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

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

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

于 2013-02-21T20:21:27.483 回答
3

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

首先注册一个中间件:

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()。

于 2017-03-28T08:37:40.080 回答
1

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

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

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

于 2013-02-21T00:32:59.787 回答
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.
  };
于 2013-02-21T01:34:19.680 回答
0

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

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

于 2013-03-08T18:43:13.313 回答
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);
        }
    }
}
于 2021-01-08T20:06:12.510 回答