一、前言
1、什麼是RateLimiter、Spring Cloud Zuul RateLimiter?
RateLimiter是Google開源的實現了令牌桶算法的限流工具(速率限制器)。http://ifeve.com/guava-ratelimiter/
Spring Cloud Zuul RateLimiter結合Zuul對RateLimiter進行了封裝,通過實現ZuulFilter提供了服務限流功能
限流粒度/類型 | 說明 |
---|---|
Authenticated User | 針對請求的用戶進行限流 |
Request Origin | 針對請求的Origin進行限流 |
URL | 針對URL/接口進行限流 |
Service | 針對服務進行限流,如果沒有配置限流類型,則此類型生效 |
https://github.com/marcosbarbero/spring-cloud-zuul-ratelimit
2、本篇主要內容
- 服務限流配置示例與說明
- URL限流配置示例與說明
- Zull集羣服務限流說明(+Redis)
- Spring Cloud Zuul RateLimiter參數介紹
3、本篇環境信息
框架 | 版本 |
---|---|
Spring Boot | 2.0.0.RELEASE |
Spring Cloud | Finchley.RELEASE |
Zuul | 1.3.1 |
JDK | 1.8.x |
4、準備工作
參考上一篇:https://ken.io/note/spring-cloud-zuul-quickstart
基於源碼:https://github.com/ken-io/springcloud-course/tree/master/chapter-08
- 準備Eureka Server、服務提供者
啓動Eureka Server: http://localhost:8800
啓動Test Service:http://localhost:8602
二、服務限流(Zuul+RateLimiter)
基於上一篇中zuul項目的源碼進行修改即可:https://github.com/ken-io/springcloud-course/tree/master/chapter-08/zuul
- 引入spring-cloud-zuul-ratelimit
<dependency>
<groupId>com.marcosbarbero.cloud</groupId>
<artifactId>spring-cloud-zuul-ratelimit</artifactId>
<version>2.0.4.RELEASE</version>
</dependency>
1、默認服務限流策略
- 修改 application.yml 配置限流策略
zuul:
ratelimit:
enabled: true
default-policy:
limit: 1
quota: 2
refresh-interval: 3
以上配置表示啓用限流策略,並且所有服務在3秒內只能有1次請求且所有請求時間總和不得超過2秒
- 限流測試
啓動zuul項目,然後訪問 http://localhost:8888/testservice?token=ken
3秒內訪問兩次,就會看到錯誤頁面
錯誤信息:type=Too Many Requests, status=429
這說明3秒內的>1次的訪問已經被限流策略擋掉
2、爲指定服務單獨配置限流策略
- 修改 application.yml 配置限流策略
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的限流策略還要更嚴格,但是這個限流並不會衝突。因爲一旦我們爲某個服務單獨配置了限流策略,那麼只有這個單獨配置的限流策略會對該服務生效。
3、基於URL的限流策略
- 修改 application.yml 配置限流策略
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去做限流。
三、Zuul集羣服務限流(Zuul+RateLimiter+Redis)
RateLimiter的限流數據是默認以ConcurrentHashMap方式存儲在內存中的,
當我們部署了Zuul集羣的時候,就會影響我們的限流策略了。我們可以將限流數據存儲在Redis中,這樣就可以集中記錄各個Zuul節點的限流數據,來保證限流的準確性。
1、部署Reids Server
參考:https://ken.io/note/centos7-redis4-setup
2、引入 Spring Data Redis
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>2.0.4.RELEASE</version>
</dependency>
3、配置Redis連接
修改application.yml
spring:
redis:
host: 192.168.88.11
port: 6379
4、配置RateLimiter數據存儲方式
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
四、備註
Zuul-RateLimiter參數說明
- Zuul-RateLimiter基本配置項
配置項 | 可選值 | 說明 |
---|---|---|
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過濾順序 |
- Policy限流策略配置項說明
項 | 說明 |
---|---|
limit | 單位時間內請求次數限制 |
quota | 單位時間內累計請求時間限制(秒),非必要參數 |
refresh-interval | 單位時間(秒),默認60秒 |
type | 限流方式:ORIGIN, USER, URL |