自己考虑的算法是这样的,先取当前时间记为startTime,然后请求判断部分,对于第一个请求判断当前时间-startTime是否小于1分钟,如果小于1分钟则请求计数加1,第二个请求判断当前时间-startTime是否小于1分钟。。。。(这里的startTime我设为static Date startTime = new Date();但是每次都会将初始的给定时间设为当前时间,这个怎样能让startTime保持为静态时间变量,当时间到达1分钟后再更新他为当前时间那)有没有大侠遇到过?
首先,这个处理应该是IP地址级别或session级别的。就是说每个IP地址或每个session做此限制。所以你这个时间设成static即jvm级别的,恐怕不大对头吧?
我的计算逻辑是这样的:
1.每个IP或session维护个访问时间的列表。
2.每次该IP或session有访问时,取当前时间,然后减去1分钟。
3.删除【1】中的列表里,所有小于【2】的时间的数据。
4.a. 如果【3】处理后的列表个数小于20,允许访问,添加本次访问时间。
4.b. 如果大于等于20,拒绝访问。
但是,除非这是你们已经规定好的逻辑。
否则,通常的限制是,刷新间隔不得小于某固定时间(比如1秒或几秒)。
逻辑就会简单多了,像你上面那样,只需要个上次访问时间即可。
但还得是IP地址或session级别的才对。
自己写个filter,拦截所有的请求
再启动个线程或者timer什么的,1分钟重置一次
要注意的是filter是两次的
是单例吗?
保证单例,然后需要起一个线程去维护静态startTime,每个1000ms,重置startTime为当前系统时间。
楼主的提问有点不知所云啊,楼主是想统计每分钟请求不超过20个么?如果某分钟请求了19个,但都集中在最后一秒,下一分钟也请求了19个,但都集中在第一秒,岂不是2秒就请求了38个了?楼主的统计方式不太对吧?或者楼主只是想维持一个一分钟刷新一次的对象?
每个IP对应一个队列(FIFO)队列长度为20,队列中保存访问时间
如果
队头 - 队尾 > 60秒 说明请求太频繁了
tcp、ip有个时间滑动窗口,不知道有没有可以借鉴的地方?其实Esper应该有相关的实现,可以参考。
作者问题提的有点模糊,我可以这样理解 吗?就是保持任何时间段(一分钟)内的请求数小于20。如果是这样的话,我们可以创建一个SIZE为20的容器(队列)。元素为time+data,也就是你说的请求。每次往里插入的时候,判断一下容器中元素的time是在一分钟之内的就可以了。如果队首的元素time在一分钟之内,队列已满(20个),刚说明一分种之内的请求已大于20了。
我觉得用queue比较好
请问你是不是需要一个这样的程序?
[code="java"]
/**
@version 1.0
*/
public class RequestOutOf20 {
static Date startTime = new Date();
static long ONE_MINUTE = 1 * 60 * 1000L;
int requestCounter = 0;
int timeCounter = 1;
void request() {
long curTime = System.currentTimeMillis();
if (curTime - startTime.getTime() > ONE_MINUTE) {
System.out.println(String.format("第%s分钟请求为%s次", timeCounter, requestCounter));
String msg = (requestCounter > 20) ? "已超过20次": "未超过20次";
System.out.println(msg);
timeCounter++;
requestCounter = 0;
startTime = new Date();
return;
}
requestCounter++;
}
public static void main(String args[]) {
RequestOutOf20 req = new RequestOutOf20();
for(int i = 0; i < 200000; i++) {
req.request();
Random r = new Random();
int interval = r.nextInt(10) * 1000;
System.out.println(String.format("间隔时间为%s秒", interval));
try {
Thread.sleep(interval);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
[/code]