您好,登錄后才能下訂單哦!
這篇文章主要講解了“如何使用ratelimiter-spring-boot-starter限流器”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“如何使用ratelimiter-spring-boot-starter限流器”吧!
基于 redis 的偏業務應用的分布式限流組件,使得項目擁有分布式限流能力變得很簡單。限流的場景有很多,常說的限流一般指網關限流,控制好洪峰流量,以免打垮后方應用。這里突出偏業務應用的分布式限流
的原因,是因為區別于網關限流,業務側限流可以輕松根據業務性質做到細粒度的流量控制。比如如下場景,
案例一:
有一個公開的 openApi 接口, openApi 會給接入方派發一個 appId,此時,如果需要根據各個接入方的 appId 限流,網關限流就不好做了,只能在業務側實現
案例二:
公司內部的短信接口,內部對接了多個第三方的短信通道,每個短信通道對流量的控制都不盡相同,假設有的第三方根據手機號和短信模板組合限流,網關限流就更不好做了
以上舉例的場景,通過 ratelimiter-spring-boot-starter 可以輕松解決限流問題
1、快速開始
maven
<dependency> <groupId>com.github.taptap</groupId> <artifactId>ratelimiter-spring-boot-starter</artifactId> <version>1.0</version> </dependency>
gradle
implementation 'com.github.taptap:ratelimiter-spring-boot-starter:1.0'
spring.ratelimiter.enabled = true spring.ratelimiter.redis-address = redis://127.0.0.1:6379 spring.ratelimiter.redis-password = xxx
啟用 ratelimiter 的配置必須加,默認不會加載。redis 相關的連接是非必須的,如果你的項目里已經使用了 Redisson
,則不用配置限流框架的 redis 連接
@RestController @RequestMapping("/test") public class TestController { @GetMapping("/get") @RateLimit(rate = 5, rateInterval = "10s") public String get(String name) { return "hello"; } }
@RateLimit 注解可以添加到任意被 spring 管理的 bean 上,不局限于 controller ,service 、repository 也可以。在最基礎限流功能使用上,以上三個步驟就已經完成了。@RateLimit 有兩個最基礎的參數,rateInterval 設置了時間窗口,rate 設置了時間窗口內允許通過的請求數量
。限流的粒度是通過限流的 key 來做的,在最基礎的設置下,限流的 key 默認是通過方法名稱拼出來的,規則如下:
key = RateLimiter_ + 類名 + 方法名
除了默認的 key 策略,ratelimiter-spring-boot-starter 充分考慮了業務限流時的復雜性,提供了多種方式。結合業務特征,達到更細粒度的限流控制。
默認觸發限流后 程序會返回一個 http 狀態碼為 429 的響應,響應值如下:
{ "code":429, "msg":"Too Many Requests" }
同時,響應的 header 里會攜帶一個 Retry-After 的時間值,單位 ms,用來告訴調用方多久后可以重試。當然這一切都是可以自定義的,進階用法可以繼續往下看
自定義限流 key 有三種方式,當自定義限流的 key 生效時,限流的 key 就變成了(默認的 key + 自定義的 key)。下面依次給出示例
@RestController @RequestMapping("/test") public class TestController { @GetMapping("/get") @RateLimit(rate = 5, rateInterval = "10s") public String get(@RateLimitKey String name) { return "get"; } }
@RateLimitKey 注解可以放在方法的入參上,要求入參是基礎數據類型,上面的例子,如果 name = kl。那么最終限流的 key 如下:
key = RateLimiter_com.taptap.ratelimiter.web.TestController.get-kl
@RestController @RequestMapping("/test") public class TestController { @GetMapping("/get") @RateLimit(rate = 5, rateInterval = "10s",keys = {"#name"}) public String get(String name) { return "get"; } @GetMapping("/hello") @RateLimit(rate = 5, rateInterval = "10s",keys = {"#user.name","user.id"}) public String hello(User user) { return "hello"; } }
keys 這個參數比 @RateLimitKey 注解更智能,基本可以包含 @RateLimitKey 的能力,只是簡單場景下,使用起來沒有 @RateLimitKey 那么便捷。keys 的語法來自 spring 的 Spel
,可以獲取對象入參里的屬性,支持獲取多個,最后會拼接起來。使用過 spring-cache 的同學可能會更加熟悉 如果不清楚 Spel
的用法,可以參考 spring-cache 的注解文檔
@RestController @RequestMapping("/test") public class TestController { @GetMapping("/get") @RateLimit(rate = 5, rateInterval = "10s",customKeyFunction = "keyFunction") public String get(String name) { return "get"; } public String keyFunction(String name) { return "keyFunction" + name; } }
當 @RateLimitKey 和 keys 參數都沒法滿足時,比如入參的值是一個加密的值,需要解密后根據相關明文內容限流。可以通過在同一類里自定義獲取 key 的函數,這個函數要求和被限流的方法入參一致,返回值為 String 類型。返回值不能為空,為空時,會回退到默認的 key 獲取策略。
spring.ratelimiter.enabled=true spring.ratelimiter.response-body=Too Many Requests spring.ratelimiter.status-code=509
添加如上配置后,觸發限流時,http 的狀態碼就變成了 509 。響應的內容變成了 Too Many Requests 了
默認的觸發限流后,限流器會拋出一個異常,限流器框架內定義了一個異常處理器來處理。自定義限流觸發處理器,需要先禁用系統默認的限流觸發處理器,禁用方式如下:
spring.ratelimiter.exceptionHandler.enable=false
然后在項目里添加自定義處理器,如下:
@ControllerAdvice public class RateLimitExceptionHandler { private final RateLimiterProperties limiterProperties; public RateLimitExceptionHandler(RateLimiterProperties limiterProperties) { this.limiterProperties = limiterProperties; } @ExceptionHandler(value = RateLimitException.class) @ResponseBody public String exceptionHandler(HttpServletResponse response, RateLimitException e){ response.setStatus(limiterProperties.getStatusCode()); response.setHeader("Retry-After", String.valueOf(e.getRetryAfter())); return limiterProperties.getResponseBody(); } }
@RequestMapping("/test") public class TestController { @GetMapping("/get") @RateLimit(rate = 5, rateInterval = "10s",fallbackFunction = "getFallback") public String get(String name) { return "get"; } public String getFallback(String name){ return "Too Many Requests" + name; } }
這種方式實現和使用和 2.1.3、自定義 key 獲取函數類似。但是多一個要求,返回值的類型需要和原限流函數的返回值類型一致,當觸發限流時,框架會調用 fallbackFunction 配置的函數執行并返回
感謝各位的閱讀,以上就是“如何使用ratelimiter-spring-boot-starter限流器”的內容了,經過本文的學習后,相信大家對如何使用ratelimiter-spring-boot-starter限流器這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。