java实现方法限流

    怎么按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; 
}

}


而我们的测试类FlowLimit就可以对方法进行调用测试了


public class FlowLimit {


private static Map<String, CacheValidate> cache = new HashMap<String, CacheValidate>();



/**
* 1. 接口限流实现 有一个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) {
// TODO Auto-generated catch block
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) {
// TODO Auto-generated catch block
e.printStackTrace();
}
FlowLimit fLimit = new FlowLimit();
System.err.println(fLimit.invoke("aaa"));
}
}
};
}

}

至此,方法限流已经完整完成,如有疑问,欢迎联系吐槽


猜你喜欢

转载自blog.csdn.net/DanielAntony/article/details/80541382