java单机接口限流处理方案详解
作者:景川呀 发布时间:2021-05-25 21:08:07
标签:java,单机,接口限流
对单机服务做接口限流的处理方案
简单说就是设定某个接口一定时间只接受固定次数的请求,比如/add接口1秒最多接收100次请求,多的直接拒绝,这个问题很常见,场景也好理解,直接上代码:
/**
* 单机限流
*/
@Slf4j
public class FlowLimit {
//接口限流上限值和限流时间缓存
private static Cache<String, AtomicLong> localCache = CacheBuilder.newBuilder().maximumSize(100)
.expireAfterWrite(1000, TimeUnit.MILLISECONDS).build();
//每个接口的上限缓存
private static Map<String, Long> maxFlowLimitMap = new ConcurrentHashMap<>();
private static final FlowLimit instance = new FlowLimit();
//这块的目的是初始化每个接口的上限,下面的变量:apiFlowLimitConfigure
//实际使用的时候应该是从db或者其他地方获取设置的每个接口的限流上限值,
//这样可以动态的调整接口上限,比如直接修改db,不用发布,就可以调整接口限流值
static {
new ScheduledThreadPoolExecutor(1, runnable -> {
Thread thread = new Thread(runnable, "api-flowLimit-configure");
// thread.setDaemon(true);
return thread;
}).scheduleAtFixedRate(() -> {
try {
String apiFlowLimitConfigure = "{\"doAdd\":100}"; //表示/doAdd接口1秒接受100次请求
Map mapObj = JSONObject.parseObject(apiFlowLimitConfigure, Map.class);
if(mapObj != null){
mapObj.forEach((key, value) -> {
if(value != null){
instance.setMaxFlowLimit(key.toString(), new Long(value.toString()));
}else{
log.warn(key + " - 设置接口限流发现限流值为空,设置默认值");
instance.setMaxFlowLimit(key.toString(), 100L);
}
});
}
} catch (Exception e) {
log.error("设置接口限流出现异常{}", e);
}
}, 0, 3, TimeUnit.SECONDS);
}
public static FlowLimit getInstance() {
return instance;
}
private FlowLimit setMaxFlowLimit(String key, Long maxFlowLimit) {
maxFlowLimitMap.put(key, maxFlowLimit);
return this;
}
public Boolean isAvailable(String key) {
return checkAvailable(key, 1L);
}
public Boolean isAvailable(String key, Long incrNum) {
return checkAvailable(key, incrNum);
}
private Boolean checkAvailable(String key, Long incrNum){
Long maxFlowLimit = maxFlowLimitMap.get(key);
if (null == maxFlowLimit || maxFlowLimit == 0) {
return true;
}
if (incrAndGet(key, incrNum) <= maxFlowLimit.longValue()) {
return true;
} else {
return false;
}
}
private long incrAndGet(String key, final long n) {
try {
return localCache.get(key, new Callable<AtomicLong>() {
@Override
public AtomicLong call() throws Exception {
return new AtomicLong(0);
}
}).addAndGet(n);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
return 0;
}
public long get(String key) {
return incrAndGet(key, 0);
}
}
上面这个就是单机限流逻辑,代码不难,感觉没必要使用ConcurrentHashMap,不过感觉无所谓了
这段代码只需要加在需要限流的接口前面:
@GetMapping("doAdd")
public Boolean doAdd(){
FlowLimit instance = FlowLimit.getInstance(); //单例获取
//查看当前的/doAdd接口是否触发了限流
Boolean flowLimitFlag = instance.isAvailable("doAdd");
if(!flowLimitFlag){
log.warn("触发限流,拒绝请求");
return false;
}
//doAdd()
return true;
}
调用实例如上
上面这个限流其实是有一定问题的:比如你限定10秒钟1000次,在第9.9秒的时候,突然进来1000个请求,然后第10.1秒的时候,攻击者,又进来1000次请求,这样,0.2秒之内,进来2000次请求。。。
所以这个时候就需要令牌桶或者其他算法了,其他算法后面再写
没怎么仔细测试,有问题欢迎提出,共同学习
来源:https://blog.csdn.net/qq_34203492/article/details/103246119


猜你喜欢
- 何为原子性原子性:一条线程在执行一系列程序指令操作时,该线程不可中断。一旦出现中断,那么就可能会导致程序执行前后的结果不一致。与数据库中的原
- struts2可以非常简单地使用FreeMarker模板作为视图技术,对于传统的jsp页面而言,FreeMarker是一个绝佳的替代方案。除
- 栈和队列的本质是相同的,都只能在线性表的一端进行插入和删除。因此,栈和队列可以相互转换。用栈实现队列—力扣232题题目要求:仅使用两个栈实现
- C#延时函数sleepsleepusing System.Threading; //导入命名空间,类Thread就在此空间中Th
- 在android中,照相功能系统已经提供,在app中可以直接使用。当手机从android play里面下载有照相功能的应用时, 会判断手机是
- C# 的类型系统可分为两种类型,一是值类型,一是引用类型,这个每个C#程序员都了解。还有托管堆,栈,ref,out等等概念也是每个C#程序员
- SpringMVC接收到请求和数据后,进行一些了的处理,当然这个处理可以是转发给Service,Service层再调用Dao层完成的,不管怎
- 一、概述近期注意到QQ新版使用了沉浸式状态栏,ok,先声明一下效果图:恩,接下来正题。首先只有大于等于4.4版本支持这个半透明状态栏的效果,
- 演示 - 初始化销毁顺序/* 初始化和销毁的执行顺序 */@SpringBootApplicationpublic
- 现象说明maven的java项目,测试用例和main所在的源码文件均符合缺省写法和格式,但是在使用mvn clean sonar:sonar
- 如何使用必应地图 WPF 控件框架使用.NET40;Visual Studio 2019;Bing Maps WPF 控件需要&n
- 本文以实例形式讲述了基于Java的图的广度优先遍历算法实现方法,具体方法如下:用邻接矩阵存储图方法:1.确定图的顶点个数和边的个数2.输入顶
- Spring Boot简介Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开
- 一、layui.use1、LayUI的官方使用文档:https://www.layui.com/doc/2、layui的内置模块不是默认就加
- app_main上一篇文章:# Android 10 启动分析之servicemanager篇 (二)在init篇中有提到,init进程会在
- 以前也模仿者ireader实现了书架的效果,但是那种是使用listview实现的,并不好用。绝大多数都是用gridview实现的,网上这方面
- // 声明LocationManager对象 LocationManager loctionManager; // 通过系统服务,取得Loc
- 本文实例为大家分享了Unity3D实现攻击范围检测的具体代码,供大家参考,具体内容如下一、扇形攻击范围检测using UnityEngine
- 本文为大家分享Android自定义Spinner适配器的相关知识点,供大家参考,具体内容如下一、大致效果二.关键代码在注释中讲重点吧。 (1
- IDEA 在接入外接屏且扩展的情况下,如果突然拔掉外接屏,就可能会产生IDEA 整个窗口只在屏幕的右侧显示一点点边框且无法拖拽到当前屏幕的情