Java中实现接口限流的方案详解
前言
今天看技术文章时看到一篇文章在讨论接口限流问题,觉得业务场景经常会使用到,就思考了一下如果是我会怎么实现?常用方案就是计数器限流方案、时间窗口限流方案和令牌桶限流方案等。这些方案的概念大致也知道,但是实际上也没有实现过,于是就自己试试实现逻辑,先动手再说。
场景
假设我们的场景是:
接口10秒内最多请求3次
思路
我想到的实现思路是有点时间窗口方案的样子,大致就是缓存请求时间,然后在每次请求的时候去校验10秒内是否超过3次请求。
图示
假设下面是请求的时间(单位:秒),那么前三次都可以请求成功,一个大小为3的数组缓存数据cache就是红框
所示:
接下去的第四个请求、第五个请求和第一个缓存时间对比,发现都小于10秒,则请求不通过。
第六个请求时间和第一个请求时间对比,时间大于10秒,所以请求通过,然后更新缓存数据cache,缓存的第一个数据改为第二个请求时间,缓存第二个数据改为第三个请求时间,缓存第三个数据改为第6个请求时间,如下图蓝框
所示,依次类推校验每次请求是否符合场景要求。
实现
1.声明一个数组cache(数组大小可以为最大请求次数3),储存请求时间;
因为我们要对比请求时间,所以讲请求缓存下来可以节省查数据库的时间。因为场景说明限制3次,所以我们只需要知道最后3个请求的时间就可以完成校验,之前的数据可以忽略。
2.首先是初始化情况,当请求小于3的时候,请求直接通过,并缓存当前请求时间;
3.当请求大于等于3的时候,判断当前请求时间和倒数第三次请求(cache[0]的数据)的间隔时间是否超过10秒,如果是则通过,否则通过。
通过的时候,要更新缓存数据,将数据前移,这次请求时间就是最后一次请求时间。
// 更新缓存 cache.set(0, cache.get(1)); cache.set(1, cache.get(2)); cache.set(2, now);
4.最后执行下代码验证下结果
完整代码如下所示:
package demo; import cn.hutool.core.date.DateUtil; import lombok.SneakyThrows; import lombok.val; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Random; /** * 限流示例,每分钟只能请求3次 */ public class LimitFlowDemo { // 记录最后3次请求时间 List<Long> cache = new ArrayList<>(); int limitTime = 10; public boolean validate() { boolean res = false; val now = DateUtil.currentSeconds(); System.out.println("当前时间:" + DateUtil.format(new Date(now * 1000), "HH:mm:ss")); if (cache.size() < 3) { res = true; cache.add(now); } else if(now - cache.get(0) > limitTime){ res = true; // 更新缓存 cache.set(0, cache.get(1)); cache.set(1, cache.get(2)); cache.set(2, now); } System.out.println("请求结果:" + res); return res; } @SneakyThrows public static void main(String[] args) { Random rd = new Random(); LimitFlowDemo demo = new LimitFlowDemo(); for (int i = 0; i < 1000; i++) { demo.validate(); // Thread.sleep(rd.nextInt(3000)); Thread.sleep(500); } } }
到此这篇关于Java中实现接口限流的方案详解的文章就介绍到这了,更多相关Java接口限流内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
springboot结合mybatis-plus快速生成项目模板的方法
Mybatis-Plus是一个 Mybatis 的增强工具,在 Mybatis 的基础上只做增强不做改变,为简化开发、提高效率而生,接下来通过本文给大家分享springboot结合mybatis-plus快速生成项目模板的方法,感兴趣的朋友一起看看吧2021-06-06springboot log4j2日志框架整合与使用过程解析
这篇文章主要介绍了springboot log4j2日志框架整合与使用,包括引入maven依赖和添加配置文件log4j2-spring.xml的相关知识,需要的朋友可以参考下2022-05-05SpringBoot中分页插件PageHelper的使用详解
分页查询是为了高效展示大量数据,通过分页将数据划分为多个部分逐页展示,原生方法需手动计算数据起始行,而使用PageHelper插件则简化这一过程,本文给大家介绍SpringBoot中分页插件PageHelper的使用,感兴趣的朋友一起看看吧2024-09-09springcloud引入spring-cloud-starter-openfeign失败的解决
这篇文章主要介绍了springcloud 引入spring-cloud-starter-openfeign失败的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教2022-03-03java synchronized同步静态方法和同步非静态方法的异同
这篇文章主要介绍了java synchronized同步静态方法和同步非静态方法的异同的相关资料,需要的朋友可以参考下2017-01-01
最新评论