有一个API网关,出于对API接口的保护,需要建立一个流控功能,根据API名称,每分钟最多只能请求指定的次数(如1000次),超过限制则这分钟内返回错误,但下一分钟又可以正常请求。
代码部分:
工具类:
public class API { /* 超时时间 */ private long time; /* 请求API的次数 */ private int count; public long getTime() { return time; } public void setTime(long time) { this.time = time; } public int getCount() { return count; } public void setCount(int count) { this.count = count; } public boolean isValid(){ System.out.println(System.currentTimeMillis()/1000); // 没有超时 if(System.currentTimeMillis()/1000 < time){ if(this.count < 10){ // 请求小于10次则表示请求成功(为了测试方便没有设为题意的1000) this.count ++; System.out.println("执行成功"); return true; }else{ System.out.println("请求超出1000次,失败"); return false; } }else{ // 触发限流则重置 System.out.println("----------重置----------"); this.count = 1; this.setTime(System.currentTimeMillis()/1000 + 1); return true; } } }
入口:
import javax.sound.midi.Soundbank; import java.util.HashMap; import java.util.Map; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class UseApi { /* * 用一个map来记录请求的名字和频次 */ private static Map<String, API> map = new HashMap<>(); public boolean invoke(String name){ if (name.isEmpty()){ return false; } synchronized (map){ System.out.println(map.containsKey(name)); // 第一次请求该命令 if(!map.containsKey(name)){ API api = new API(); api.setTime(System.currentTimeMillis()/1000 + 1); api.setCount(1); map.put(name, api); return true; }else{ API api = map.get(name); return api.isValid(); } } } // 测试方法,线程里面请求10次同一个方法 method1 public static Runnable getThread(){ return new Runnable() { @Override public void run() { for(int i = 0; i < 10; i ++){ try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } UseApi useApi = new UseApi(); System.out.println(useApi.invoke("method1")); } } }; } public static void main(String[] args) { ExecutorService executorService = Executors.newFixedThreadPool(10); // 开10个线程进行测试 for (int i = 0; i < 10; i++) { executorService.submit(getThread()); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } executorService.shutdown(); } }