怎么按apiName作为参数做一个方法限流,相信大家对方法限流的运用场景并不少见,首先,
我们就来分析方法限流的实现过程:
第一,方法限流必须保证线程安全,这里我们先来介绍一下什么是线程安全:
线程安全简单来说就是在多线程访问一个对象的时候,对象的值/状态不会因为多线程的环境而产生影响。
第二,我们需要通过时间和调用频率来限制该对象的调用,所以比较好的方法是通过一个对象来存储
每个apiName对应的调用情况(时间和频率),如下我们用CacheValidate类来进行存储,我们采用
isValidate方法判断调用次数是否超限。
这时候,我们的思路就很明显了,我们需要用一个map对象进行apiName(key)和
CacheValidate(value)的存储。
public class CacheValidate {
private long time;
private int invokeNum;
public long getTime() {
return time;
}
public void setTime(long time) {
this.time = time;
}
public int getInvokeNum() {
return invokeNum;
}
public void setInvokeNum(int invokeNum) {
this.invokeNum = invokeNum;
}
/**
* 校验方法是否有效
*/
public boolean isValidate() {
this.invokeNum = invokeNum + 1;
if (System.currentTimeMillis() / 1000 <= time) {
System.err.println(System.currentTimeMillis() / 1000);
if (invokeNum <= 60) {
System.err.println("isValidate");
return true;
} else {
System.err.println("大于60次");
}
} else {
this.invokeNum = 1;
this.time = System.currentTimeMillis() / 1000;
return true;
}
return false;
}
}
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class FlowLimit {
private static Map cache = new HashMap();
/**
* 接口限流实现 有一个API网关,出于对API接口的保护,需要建立一个流控功能,
* 根据API名称,每分钟最多只能请求指定的次数(如1000次),超过限制则这分
* 钟内返回错误,但下一分钟又可以正常请求。 接口定义对invoke方法进行调用,
* 超过限制则return false。
*/
public boolean invoke(String apiName) {
if(apiName==null){
return false;
}
CacheValidate cacheValidate = null;
synchronized (cache) {
cacheValidate = cache.get(apiName);
if(cacheValidate==null){
cacheValidate = new CacheValidate();
cacheValidate.setTime(System.currentTimeMillis()/1000+5);
cacheValidate.setInvokeNum(1);
cache.put(apiName, cacheValidate);
return true;
}
return cacheValidate.isValidate();
}
}
public static void main(String[] args) {
ExecutorService service = Executors.newFixedThreadPool(10);
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(700);
} catch (InterruptedException e) {
e.printStackTrace();
}
service.submit(getTask());
}
service.shutdown();
}
public static Runnable getTask(){
return new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
FlowLimit fLimit = new FlowLimit();
System.err.println(fLimit.invoke("apiName"));
}
}
};
}
}
注意:本文归作者所有,未经作者允许,不得转载