Java实现接口限流方案
这篇文章主要为大家详细介绍了Java实现接口限流方案,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
本文实例为大家分享了Java实现接口限流方案的具体代码,供大家参考,具体内容如下
RateLimiter
Google开源工具包Guava提供了限流工具类RateLimiter,基于令牌桶算法实现。
1.maven依赖:
1 2 3 4 5 | < dependency > < groupId >com.google.guava</ groupId > < artifactId >guava</ artifactId > < version >27.1-jre</ version > </ dependency > |
2.自定义注解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | import java.lang.annotation.*; import java.util.concurrent.TimeUnit; /** * 令牌桶注解实现 */ @Target ({ElementType.METHOD}) @Retention (RetentionPolicy.RUNTIME) @Documented public @interface RequestLimiter { /** * 每秒创建令牌个数,默认:10 */ double QPS() default 10D; /** * 获取令牌等待超时时间 默认:500 */ long timeout() default 500 ; /** * 超时时间单位 默认:毫秒 */ TimeUnit timeunit() default TimeUnit.MILLISECONDS; /** * 无法获取令牌返回提示信息 */ String msg() default "请稍后再试!" ; } |
3.拦截器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.google.common.util.concurrent.RateLimiter; import com.tiam.panshi.cloud.appback.annotation.RequestLimiter; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.HandlerInterceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.PrintWriter; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @Component @Slf4j public class RequestLimitingInterceptor implements HandlerInterceptor { private final Map<String, RateLimiter> rateLimiterMap = new ConcurrentHashMap<>(); @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { //这里可以抽出去定义返回信息 JSONObject jsonObject = new JSONObject(); jsonObject.put( "10001" , "玩命加载中,请稍后再试" ); try { if (handler instanceof HandlerMethod) { HandlerMethod handlerMethod = (HandlerMethod) handler; RequestLimiter rateLimit = handlerMethod.getMethodAnnotation(RequestLimiter. class ); //判断是否有注解 if (rateLimit != null ) { // 获取请求url String url = request.getRequestURI(); RateLimiter rateLimiter; // 判断map集合中是否有创建好的令牌桶 if (!rateLimiterMap.containsKey(url)) { // 创建令牌桶,以n r/s往桶中放入令牌 rateLimiter = RateLimiter.create(rateLimit.QPS()); rateLimiterMap.put(url, rateLimiter); } rateLimiter = rateLimiterMap.get(url); // 获取令牌 boolean acquire = rateLimiter.tryAcquire(rateLimit.timeout(), rateLimit.timeunit()); if (acquire) { //获取令牌成功 return true ; } else { log.warn( "请求被限流,url:{}" , request.getServletPath()); makeResult(response, renderJson(jsonObject)); return false ; } } } return true ; } catch (Exception var6) { var6.printStackTrace(); makeResult(response, renderJson(jsonObject)); return false ; } } private void makeResult(HttpServletResponse response, JSONObject jo) { response.setContentType( "application/json; charset=utf-8" ); response.setCharacterEncoding( "UTF-8" ); try (PrintWriter out = response.getWriter()) { out.append(jo.toJSONString()); } catch (Exception e) { e.printStackTrace(); } } private JSONObject renderJson(Object o) { return JSONObject.parseObject(JSON.toJSONString(o)); } |
4.注册拦截器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | @Configuration public class WebMvcConfig extends WebMvcConfigurationSupport { /** * 请求限流拦截器 */ @Autowired protected RequestLimitingInterceptor requestLimitingInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { // 请求限流 registry.addInterceptor(requestLimitingInterceptor).addPathPatterns( "/**" ); } } |
5.在接口上配置注解
1 2 3 4 5 6 | @RequestLimiter (QPS = 5D, timeout = 200 , timeunit = TimeUnit.MILLISECONDS,msg = "玩命加载中,请稍后再试" ) @GetMapping ( "/test" ) @ResponseBody public String test(){ return "" ; } |
以上就是本文的全部内容,希望对大家的学习有所帮助
原文链接:https://blog.csdn.net/JST888_K/article/details/121522459