您好,登錄后才能下訂單哦!
小編給大家分享一下Java如何實現接口限流,希望大家閱讀完這篇文章之后都有所收獲,下面讓我們一起去探討吧!
RateLimiter
Google開源工具包Guava提供了限流工具類RateLimiter,基于令牌桶算法實現。
<dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>27.1-jre</version> </dependency>
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 "請稍后再試!"; }
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)); }
@Configuration public class WebMvcConfig extends WebMvcConfigurationSupport { /** * 請求限流攔截器 */ @Autowired protected RequestLimitingInterceptor requestLimitingInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { // 請求限流 registry.addInterceptor(requestLimitingInterceptor).addPathPatterns("/**"); } }
@RequestLimiter(QPS = 5D, timeout = 200, timeunit = TimeUnit.MILLISECONDS,msg = "玩命加載中,請稍后再試") @GetMapping("/test") @ResponseBody public String test(){ return ""; }
看完了這篇文章,相信你對“Java如何實現接口限流”有了一定的了解,如果想了解更多相關知識,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。