通过JS实现消息防洪
Implementing message flood protection via JS
我目前是 运行 服务器。我编写的一个机器人目前为版主提供管理工具,但我希望该机器人也有某种内置的自动防洪系统。
所以我可以访问用户发送的每条消息,发送消息的用户的姓名,以及他们发送消息的时间。我不确定如何着手制作一个系统,有人有什么想法吗?我希望能够为服务器中的每个用户适度防洪。
创建一个以用户名为关键字的地图。每个用户的值应该是一个长度为 n
(比如说十)的循环数组。每个循环数组的内容应该是请求的时间戳。
在每个入站请求中,从该用户名的数组中获取第 n
项。从 performance.now()
中减去它,然后计算该比率是否可以接受。如果不是,则执行空操作,或 return HTTP 错误代码。
以下代码是说明性的,并非功能性代码。
var Q_LENGTH = 10;
var MAX_REQUEST_RATE = 1; // per second
var requestTimeMap = {};
function onRequest(username, timestamp) {
recordReq(username);
if(tooFast(username)) {
// return HTTP 40x
}
// service the request
}
function recordReq(username) {
requestTimeMap[username] = requestTimeMap.username || createCircularQ(Q_LENGTH);
requestTimeMap[username].unshift(performance.now())
}
function tooFast(username) {
return ((performance.now() - (requestTimeMap[username][Q_LENGTH] || 0)) / Q_LENGTH) > (1000 / MAX_REQUEST_RATE);
}
function createCircularQ(length) {
var circularQueue = [];
circularQueue.unshift = function(element) {
if (this.length === length) {
this.pop();
}
return Array.prototype.unshift.call(this, element);
}
return circularQueue;
}
我目前是 运行 服务器。我编写的一个机器人目前为版主提供管理工具,但我希望该机器人也有某种内置的自动防洪系统。
所以我可以访问用户发送的每条消息,发送消息的用户的姓名,以及他们发送消息的时间。我不确定如何着手制作一个系统,有人有什么想法吗?我希望能够为服务器中的每个用户适度防洪。
创建一个以用户名为关键字的地图。每个用户的值应该是一个长度为 n
(比如说十)的循环数组。每个循环数组的内容应该是请求的时间戳。
在每个入站请求中,从该用户名的数组中获取第 n
项。从 performance.now()
中减去它,然后计算该比率是否可以接受。如果不是,则执行空操作,或 return HTTP 错误代码。
以下代码是说明性的,并非功能性代码。
var Q_LENGTH = 10;
var MAX_REQUEST_RATE = 1; // per second
var requestTimeMap = {};
function onRequest(username, timestamp) {
recordReq(username);
if(tooFast(username)) {
// return HTTP 40x
}
// service the request
}
function recordReq(username) {
requestTimeMap[username] = requestTimeMap.username || createCircularQ(Q_LENGTH);
requestTimeMap[username].unshift(performance.now())
}
function tooFast(username) {
return ((performance.now() - (requestTimeMap[username][Q_LENGTH] || 0)) / Q_LENGTH) > (1000 / MAX_REQUEST_RATE);
}
function createCircularQ(length) {
var circularQueue = [];
circularQueue.unshift = function(element) {
if (this.length === length) {
this.pop();
}
return Array.prototype.unshift.call(this, element);
}
return circularQueue;
}