Java实现QPS控制
2016-03-23 15:33
519 查看
Java实现QPS控制
什么是QPSQPS:queries per second :每秒的请求数
QPS控制的目的
防止恶意刷取,增加项目负载
解决方案1(假设需要控制在1s内不多于400个请求):
方案描述:
使用数组存储每个请求到来的时间,前400次请求顺利通过,并填满数组。
后续请求到来时,判断当前时间是否比数组中最早的时间晚1s,未晚,则打回,
晚则替换数组中最早的值。循环。
代码实现:
import java.util.Arrays; import java.util.concurrent.TimeUnit; public class WindowQpsControl { /** * 接受请求窗口 */ private Long[] accessWindow; /** * 窗口大小 */ private int limit; /** * 指针位置 */ private int curPosition; /** * 时间间隔 */ private long period; private final Object lock = new Object(); /** * 1秒内最多400次请求 * @param limit 限制次数 400 * @param period 时间间隔 1 * @param timeUnit 间隔类型 秒 */ public WindowQpsControl(int limit, int period, TimeUnit timeUnit) { if (limit < 0) { throw new IllegalArgumentException("Illegal Capacity: " + limit); } curPosition = 0; this.period = timeUnit.toMillis(period); this.limit = limit; accessWindow = new Long[limit]; Arrays.fill(accessWindow, 0); } public boolean isPass() { long curTime = System.currentTimeMillis(); synchronized (lock) { if (curTime >= period + accessWindow[curPosition]) { accessWindow[curPosition++] = curTime; curPosition = curPosition % limit; return true; } else { return false; } } } }
解决方案2(假设需要控制在1s内不多于400个请求):
方案描述:
使用两个辅助变量:limitPoint:当前时间点,初始化为当前时间
count:通过的访问数,初始化为0,没接收一次请求,自加1
count <= 400时请求可以顺利通过,每通过一次,count++;
count > 400请求到来时,判断当前时间是否比limitPoint晚1s,未晚1s,打回;
满则将limitPoint置为当前时间,count置0。循环。
代码展示:
import java.util.concurrent.TimeUnit; public class PointQpsControl { private long limitPoint; private int count = 0; /** * 窗口大小 */ private int limit; /** * 时间间隔 */ private long period; private final Object lock = new Object(); /** * 1秒内最多400次请求 * @param limit 限制次数 * @param period 时间间隔 * @param timeUnit 间隔类型 */ public PointQpsControl(int limit, int period, TimeUnit timeUnit) { limitPoint = System.currentTimeMillis(); curPosition = 0; this.period = timeUnit.toMillis(period); this.limit = limit; } public boolean isPass() { long curTime = System.currentTimeMillis(); synchronized (lock) { if (count > limit) { if (curTime - limitPoint > period) { limitPoint = curTime; count = 0; return true; } else { return false; } } else { count++; return true; } } } }
方案对比:
对比 | |
---|---|
空间效率 | 严格说,方案一中的时间窗口需要额外的数组存储,较方案二,浪费空间 |
时间效率 | 严格说,方案一需要数组存储,数组存于堆中,较方案二,读写慢 |
稳定性 | 方案一可以保证在任意时间段(1s)内,请求数不超过400。方案二可能出现在某个时间段(1s)内,接收的请求数达到800。 |
注:这两个方案是我和导师,老大三个人讨论出来的(老大不愧是老大)
相关文章推荐
- Java [Leetcode 94]Binary Tree Inorder Traversal
- Spring 学习转载
- 图文介绍如何在Eclipse统计代码行数
- spring ioc
- MyEclipse6.5安装SVN插件的三种方法 以及基本操作
- Myeclipse10不支持编译器1.7
- Java中getBytes()的用法
- Spring IOC
- hadoop java.lang.RuntimeException: java.lang.NoSuchMethodException
- eclipse过一会就出现Adb connection Error:远程主机强迫关闭了一个现有的连接。
- Java泛型初探
- java: 异常处理
- Java基础 foreach实现原理
- Java第三次实验要求
- Java实现剪切复制粘贴功能(含不同文本域的判断)
- Java管道流PipedStream
- java tar.gz文件生成
- JAVA复习(7)-线程间通信
- 关于用gradle构建spring源码环境的多次尝试
- Spring Bean的延迟初始化