RateLimiter是Google開源的實現了令牌桶算法的限流工具(速率限制器)。http://ifeve.com/guava-ratelimiter/git
Spring Cloud Zuul RateLimiter結合Zuul對RateLimiter進行了封裝,經過實現ZuulFilter提供了服務限流功能github
限流粒度/類型 | 說明 |
---|---|
Authenticated User | 針對請求的用戶進行限流 |
Request Origin | 針對請求的Origin進行限流 |
URL | 針對URL/接口進行限流 |
Service | 針對服務進行限流,若是沒有配置限流類型,則此類型生效 |
https://github.com/marcosbarbero/spring-cloud-zuul-ratelimitredis
框架 | 版本 |
---|---|
Spring Boot | 2.0.0.RELEASE |
Spring Cloud | Finchley.RELEASE |
Zuul | 1.3.1 |
JDK | 1.8.x |
參考上一篇:https://ken.io/note/spring-cloud-zuul-quickstart
基於源碼:https://github.com/ken-io/springcloud-course/tree/master/chapter-08算法
啓動Eureka Server: http://localhost:8800
啓動Test Service:http://localhost:8602spring
基於上一篇中zuul項目的源碼進行修改便可:https://github.com/ken-io/springcloud-course/tree/master/chapter-08/zuulcentos
<dependency> <groupId>com.marcosbarbero.cloud</groupId> <artifactId>spring-cloud-zuul-ratelimit</artifactId> <version>2.0.4.RELEASE</version> </dependency>
zuul: ratelimit: enabled: true default-policy: limit: 1 quota: 2 refresh-interval: 3
以上配置表示啓用限流策略,而且全部服務在3秒內只能有1次請求且全部請求時間總和不得超過2秒app
啓動zuul項目,而後訪問 http://localhost:8888/testservice?token=ken
3秒內訪問兩次,就會看到錯誤頁面框架
錯誤信息:type=Too Many Requests, status=429
這說明3秒內的>1次的訪問已經被限流策略擋掉spring-boot
zuul: ratelimit: enabled: true default-policy: limit: 1 quota: 1 refresh-interval: 3 policies: testservice: limit: 10 quota: 50 refresh-interval: 60
以上配置單獨爲testservice配置了限流策略。60秒內訪問次數不得查過10次且訪問時間這不得超過50秒。工具
雖然咱們也同時配置了默認限流策略,並且默認限流策略比testservice的限流策略還要更嚴格,可是這個限流並不會衝突。由於一旦咱們爲某個服務單獨配置了限流策略,那麼只有這個單獨配置的限流策略會對該服務生效。
zuul: ratelimit: enabled: true default-policy: limit: 1 quota: 1 refresh-interval: 3 policies: testservice: limit: 10 quota: 50 refresh-interval: 60 type: url
以上配置只是在testservice的策略上增長了type參數的設置。(固然也能夠在默認策略加這個參數)。
那麼這個策略就變成了:每一個Url60秒內訪問次數不得超過10次且總計訪問時間這不得超過50秒。
啓動zuul項目,而後訪問: http://localhost:8888/testservice?token=ken
達到限流閾值後,訪問:
http://localhost:8888/testservice/plus?token=ken&numA=1&numB=2
依然能夠正常訪問。
另外,須要值得注意的是,?
後面的參數是不會做爲限流的key的。
http://localhost:8888/testservice?token=ken , http://localhost:8888/testservice?token=ken.io 會被做爲同一個url進行限流
若是zuul-ratelimiter的限流粒度/方式不能知足你的需求,你能夠選擇自定義ZuulFilter集成RateLimiter去作限流。
RateLimiter的限流數據是默認以ConcurrentHashMap方式存儲在內存中的,
當咱們部署了Zuul集羣的時候,就會影響咱們的限流策略了。咱們能夠將限流數據存儲在Redis中,這樣就能夠集中記錄各個Zuul節點的限流數據,來保證限流的準確性。
參考:https://ken.io/note/centos7-redis4-setup
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> <version>2.0.4.RELEASE</version> </dependency>
修改application.yml
spring: redis: host: 192.168.88.11 port: 6379
zuul: ratelimit: enabled: true repository: redis default-policy: limit: 1 quota: 1 refresh-interval: 3 policies: testservice: limit: 10 quota: 50 refresh-interval: 60 type: url
配置項 | 可選值 | 說明 |
---|---|---|
enabled | true/false | 是否啓用限流 |
behind-proxy | true/false | 翻了源碼,沒發現有使用。。。做者也沒說明。。。 |
key-prefix | String | 限流key前綴 |
repository | CONSUL, REDIS, JPA, BUCKET4J_JCACHE, BUCKET4J_HAZELCAST, BUCKET4J_INFINISPAN, BUCKET4J_IGNITE, IN_MEMORY | 限流數據的存儲方式,默認是:IN_MEMORY |
default-policy | — | 默認策略 |
policies | — | 自定義策略 |
postFilterOrder | — | postFilter過濾順序 |
preFilterOrder | — | preFilter過濾順序 |
項 | 說明 |
---|---|
limit | 單位時間內請求次數限制 |
quota | 單位時間內累計請求時間限制(秒),非必要參數 |
refresh-interval | 單位時間(秒),默認60秒 |
type | 限流方式:ORIGIN, USER, URL |
https://github.com/ken-io/springcloud-course/tree/master/chapter-09
https://github.com/marcosbarbero/spring-cloud-zuul-ratelimit