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

问题描述:

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

什么是最简单的方式获得反馈给客户,它是压倒性的服务器,需要放慢速度?我喜欢socket.pause()socket.resume(),因为它不需要客户端的任何附加代码 - 备份TCP套接字,事情自然放慢。任何等效的socket.io?

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

随着足够的挖掘,我发现这个:

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

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

授予此如果socket.io连接不是网络插座连接可能无法工作,并在以后的更新可能会中断,但现在我会去它。当我在未来得到一些时间时,我可能会将它改为Pascal提出的QUOTA_EXCEEDED解决方案。

+1

你会如何使用它?例如,在客户端连接并且你有套接字之后,你把这个代码放在哪里? – Justin 2014-08-01 21:50:38

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

做到这一点的一种方法是让客户等待每个发射的回应,然后再发射其他东西。通过这种方式,服务器可以通过仅在准备就绪时回答客户端可以发送的速度,或者仅在设定的时间后回答。

如果这还不够,当客户端每秒超出x次请求时,开始回复类似QUOTA_EXCEEDED错误的错误,并忽略它们发送的数据。这将迫使外部开发人员让他们的应用按照您的需要行事做。

+0

不幸的是,我只是提供一个API来与服务器交互;我无法直接控制客户的工作方式。这就是为什么'socket.pause()'如此完美 - 客户端无法绕过TCP流的阻塞。 – Zik 2013-02-21 03:57:42

+0

那么,如果客户端开始发送太多的请求,就像QUOTA_EXCEEDED一样发回一个错误。这是很多API所做的。这应该引起客户的注意,也是它的开发者。试着明确客户是否超出每分钟配额或每日配额。 – 2013-02-21 07:33:41

如果您对您的服务器的某个地方的回调通常发回给你的客户端的响应,你可以尝试改变它像这样:

前:

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

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

对所有消息都有响应,但客户端在发送更多数据之前不必等待响应。客户端不是由我写的,所以我无法控制它的工作方式。 – Zik 2013-02-21 03:56:05

+0

我明白了。这是您想要调节的传入请求。我想你需要查看socket.io代码,看看你是否可以访问套接字(这将在某处)。好挑战! (我同意做服务器端是最好的) – AndyD 2013-02-21 10:37:55

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

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

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

首先注册一个中间件:

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()代替日期。时间()。