Module to enable rate limit per service in Netflix Zuul.
There are five built-in rate limit approaches:
Authenticated User
Uses the authenticated username or 'anonymous'
Request Origin
Uses the user origin request
URL
Uses the request path of the downstream service
URL Pattern
Uses the request Ant path pattern to the downstream service
ROLE
Uses the authenticated user roles
Request method
Uses the HTTP request method
Global configuration per service:
This one does not validate the request Origin, Authenticated User or URI
To use this approach just don’t set param 'type'
Note
|
It is possible to combine Authenticated User, Request Origin, URL, ROLE and Request Method just adding multiple values to the list |
Note
|
If you are using Spring Boot version |
Add the dependency on pom.xml
<dependency>
<groupId>com.marcosbarbero.cloud</groupId>
<artifactId>spring-cloud-zuul-ratelimit</artifactId>
<version>LATEST</version>
</dependency>
Add the following dependency accordingly to the chosen data storage:
Redis
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
Consul
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul</artifactId>
</dependency>
Spring Data JPA
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
Bucket4j JCache
<dependency>
<groupId>com.github.vladimir-bukhtoyarov</groupId>
<artifactId>bucket4j-core</artifactId>
</dependency>
<dependency>
<groupId>com.github.vladimir-bukhtoyarov</groupId>
<artifactId>bucket4j-jcache</artifactId>
</dependency>
<dependency>
<groupId>javax.cache</groupId>
<artifactId>cache-api</artifactId>
</dependency>
Bucket4j Hazelcast (depends on Bucket4j JCache)
<dependency>
<groupId>com.github.vladimir-bukhtoyarov</groupId>
<artifactId>bucket4j-hazelcast</artifactId>
</dependency>
<dependency>
<groupId>com.hazelcast</groupId>
<artifactId>hazelcast</artifactId>
</dependency>
Bucket4j Infinispan (depends on Bucket4j JCache)
<dependency>
<groupId>com.github.vladimir-bukhtoyarov</groupId>
<artifactId>bucket4j-infinispan</artifactId>
</dependency>
<dependency>
<groupId>org.infinispan</groupId>
<artifactId>infinispan-core</artifactId>
</dependency>
Bucket4j Ignite (depends on Bucket4j JCache)
<dependency>
<groupId>com.github.vladimir-bukhtoyarov</groupId>
<artifactId>bucket4j-ignite</artifactId>
</dependency>
<dependency>
<groupId>org.apache.ignite</groupId>
<artifactId>ignite-core</artifactId>
</dependency>
Sample YAML configuration
zuul:
ratelimit:
key-prefix: your-prefix
enabled: true
repository: REDIS
behind-proxy: true
add-response-headers: true
default-policy-list: #optional - will apply unless specific policy exists
- limit: 10 #optional - request number limit per refresh interval window
quota: 1000 #optional - request time limit per refresh interval window (in seconds)
refresh-interval: 60 #default value (in seconds)
type: #optional
- user
- origin
- url
- http_method
policy-list:
myServiceId:
- limit: 10 #optional - request number limit per refresh interval window
quota: 1000 #optional - request time limit per refresh interval window (in seconds)
refresh-interval: 60 #default value (in seconds)
type: #optional
- user
- origin
- url
- type: #optional value for each type
- user=anonymous
- origin=somemachine.com
- url=/api #url prefix
- role=user
- http_method=get #case insensitive
- type:
- url_pattern=/api/*/payment
Sample Properties configuration
zuul.ratelimit.enabled=true
zuul.ratelimit.key-prefix=your-prefix
zuul.ratelimit.repository=REDIS
zuul.ratelimit.behind-proxy=true
zuul.ratelimit.add-response-headers=true
zuul.ratelimit.default-policy-list[0].limit=10
zuul.ratelimit.default-policy-list[0].quota=1000
zuul.ratelimit.default-policy-list[0].refresh-interval=60
# Adding multiple rate limit type
zuul.ratelimit.default-policy-list[0].type[0]=user
zuul.ratelimit.default-policy-list[0].type[1]=origin
zuul.ratelimit.default-policy-list[0].type[2]=url
zuul.ratelimit.default-policy-list[0].type[3]=http_method
# Adding the first rate limit policy to "myServiceId"
zuul.ratelimit.policy-list.myServiceId[0].limit=10
zuul.ratelimit.policy-list.myServiceId[0].quota=1000
zuul.ratelimit.policy-list.myServiceId[0].refresh-interval=60
zuul.ratelimit.policy-list.myServiceId[0].type[0]=user
zuul.ratelimit.policy-list.myServiceId[0].type[1]=origin
zuul.ratelimit.policy-list.myServiceId[0].type[2]=url
# Adding the second rate limit policy to "myServiceId"
zuul.ratelimit.policy-list.myServiceId[1].type[0]=user=anonymous
zuul.ratelimit.policy-list.myServiceId[1].type[1]=origin=somemachine.com
zuul.ratelimit.policy-list.myServiceId[1].type[2]=url_pattern=/api/*/payment
zuul.ratelimit.policy-list.myServiceId[1].type[3]=role=user
zuul.ratelimit.policy-list.myServiceId[1].type[4]=http_method=get
There are eight implementations provided:
Implementation | Data Storage |
---|---|
ConsulRateLimiter |
|
RedisRateLimiter |
|
SpringDataRateLimiter |
|
Bucket4jJCacheRateLimiter |
|
Bucket4jHazelcastRateLimiter |
|
Bucket4jIgniteRateLimiter |
|
Bucket4jInfinispanRateLimiter |
Bucket4j implementations require the relevant bean with @Qualifier("RateLimit")
:
JCache
- javax.cache.Cache
Hazelcast
- com.hazelcast.core.IMap
Ignite
- org.apache.ignite.IgniteCache
Infinispan
- org.infinispan.functional.ReadWriteMap
Property namespace: zuul.ratelimit
Property name | Values | Default Value |
---|---|---|
enabled |
true/false |
false |
behind-proxy |
true/false |
false |
add-response-headers |
true/false |
true |
key-prefix |
String |
${spring.application.name:rate-limit-application} |
repository |
CONSUL, REDIS, JPA, BUCKET4J_JCACHE, BUCKET4J_HAZELCAST, BUCKET4J_INFINISPAN, BUCKET4J_IGNITE |
- |
default-policy-list |
List of Policy |
- |
policy-list |
Map of Lists of Policy |
- |
postFilterOrder |
int |
FilterConstants.SEND_RESPONSE_FILTER_ORDER - 10 |
preFilterOrder |
int |
FilterConstants.FORM_BODY_WRAPPER_FILTER_ORDER |
Policy properties:
Property name | Values | Default Value |
---|---|---|
limit |
number of calls |
- |
quota |
time of calls |
- |
refresh-interval |
seconds |
60 |
type |
[ORIGIN, USER, URL, URL_PATTERN, ROLE, HTTP_METHOD] |
[] |
breakOnMatch |
true/false |
false |
This section details how to add custom implementations
If the application needs to control the key strategy beyond the options offered by the type property then it can
be done just by creating a custom RateLimitKeyGenerator
implementation adding further qualifiers or something entirely different:
@Bean
public RateLimitKeyGenerator ratelimitKeyGenerator(RateLimitProperties properties, RateLimitUtils rateLimitUtils) {
return new DefaultRateLimitKeyGenerator(properties, rateLimitUtils) {
@Override
public String key(HttpServletRequest request, Route route, RateLimitProperties.Policy policy) {
return super.key(request, route, policy) + ":" + request.getMethod();
}
};
}
This framework uses some 3rd party applications to store and control the rate limit access, as it does not has control
over those applications and they can fail once a while the framework itself handles the failure in the class
DefaultRateLimiterErrorHandler
just by adding some error logs.
If there is a need to handle the errors differently, it can be achieved just by defining a custom
RateLimiterErrorHandler
bean, e.g:
@Bean
public RateLimiterErrorHandler rateLimitErrorHandler() {
return new DefaultRateLimiterErrorHandler() {
@Override
public void handleSaveError(String key, Exception e) {
// custom code
}
@Override
public void handleFetchError(String key, Exception e) {
// custom code
}
@Override
public void handleError(String msg, Exception e) {
// custom code
}
}
}
Spring Cloud Zuul Rate Limit is released under the non-restrictive Apache 2.0 license, and follows a very standard Github development process, using Github tracker for issues and merging pull requests into master. If you want to contribute even something trivial please do not hesitate, but follow the guidelines below.
This project adheres to the Contributor Covenant code of conduct. By participating, you are expected to uphold this code. Please report unacceptable behavior to marcos.hgb@gmail.com.
Any doubt open an issue. Any fix send me a Pull Request.
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。