github https://github.com/marcosbarbero/spring-cloud-zuul-ratelimit

Spring – the cloud – zuul – ratelimit

Spring-cloud-zuul-ratelimit is an extension that integrates with Zuul to provide distributed traffic limiting policies

  • Limit the flow of the requested target URL (e.g., how many calls to a URL are allowed per minute)
  • Limit the flow of client access IP addresses (for example, how many requests are allowed per minute for an IP address)
  • Limit traffic for certain users or user groups (for example, non-VIP users can only call an API 100 times per minute)
  • Multi-dimensional mixed current limiting. At this point, it is necessary to implement some flow limiting rules orchestration mechanism. And, or, not equal relationship.

Supported traffic limiting granularity

  • Service granularity (default, traffic limiting for the current service module)
  • Implementation of user granularity user traffic limiting: If your project integrates Shiro or Spring Security frameworks, the Request domain UserPrincipal will be maintained automatically. If it is your own framework, please maintain the Request domain UserPrincipal after successful login to use user-granularity traffic limiting. The default value is anonymous
  • ORIGIN granularity (The ORIGIN requested by the user serves as granularity control.) Traffic limiting on a client with a certain IP address does not affect other clients. That is, the API gateway is independent of each client
  • URL interface granularity (the address of the request interface as granularity control)
  • The above granularity is freely combined and can support a variety of situations.
  • If that’s not enough, customize the RateLimitKeyGenerator implementation

Data storage support

  • InMemoryRateLimiter – Uses ConcurrentHashMap as the data store
  • ConsulRateLimiter – Use Consul for data storage
  • RedisRateLimiter – Uses Redis as the data store
  • JpaRateLimiter – Uses the database as the data store
  • Bucket4j JCache and other cache stores

Pom depends on

<dependency> <groupId>com.marcosbarbero.cloud</groupId> <artifactId>spring-cloud-zuul-ratelimit</artifactId> < version > 1.7.1. RELEASE < / version > < / dependency > < the dependency > < groupId > org. Springframework. Boot < / groupId > <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>Copy the code

Current limiting configuration

  • Limit Indicates the number of accesses allowed in a unit of time
  • Quota Specifies the number of requests that can be accessed per unit of time (within a unit time window, all requests cannot exceed this limit)
  • Refresh-interval Specifies the unit time
  • Type Traffic limiting type
    • Traffic limiting of URL types is differentiated by request path
    • Origin is distinguished by client IP address
    • Users are distinguished by login user names, including anonymous users
  • Default-policy Optional – Indicates the policy configured for all routes, unless policy-list is specified
  • Policies Limits traffic of a specific service ID
    • disadvantages
      • Multiple urls can be configured, but each URL uses a traffic limiting configuration. There is no way to specify the traffic limiting configuration for each URL
  • Policy-list Indicates traffic limiting for specific service ids
    • advantages
      • You can specify a different traffic limiting configuration for each URL of a service ID

Policies Specifies the number of traffic limiting times shared by multiple urls

zuul.routes.hello-feign.path=/hello-feign/**
zuul.routes.hello-feign.serviceId=feign-service-1

# * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
# Specific route
#
Test client allows 10 accesses in 30 seconds and requires total request time less than 20 seconds
#
# * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
zuul.ratelimit.policies.hello-feign.limit=10
zuul.ratelimit.policies.hello-feign.quota=20
zuul.ratelimit.policies.hello-feign.refreshInterval=30

zuul.ratelimit.policies.hello-feign.type[0].type=url
zuul.ratelimit.policies.hello-feign.type[0].matcher=/custom/zuul/test

zuul.ratelimit.policies.hello-feign.type[1].type=url
zuul.ratelimit.policies.hello-feign.type[1].matcher=/custom/zuul/timeout
Copy the code

Policy-list Specifies the traffic limiting times for each URL

zuul.routes.hello-feign.path=/hello-feign/**
zuul.routes.hello-feign.serviceId=feign-service-1

zuul.ratelimit.policy-list.hello-feign.[0].limit=10
zuul.ratelimit.policy-list.hello-feign.[0].quota=4
zuul.ratelimit.policy-list.hello-feign.[0].refreshInterval=10
zuul.ratelimit.policy-list.hello-feign.[0].type[0].type=url
zuul.ratelimit.policy-list.hello-feign.[0].type[0].matcher=/custom/zuul/test

zuul.ratelimit.policy-list.hello-feign.[1].limit=2
zuul.ratelimit.policy-list.hello-feign.[1].quota=4
zuul.ratelimit.policy-list.hello-feign.[1].refreshInterval=10
zuul.ratelimit.policy-list.hello-feign.[1].type[0].type=url
zuul.ratelimit.policy-list.hello-feign.[1].type[0].matcher=/request-body
Copy the code

Extend the key generated by the policy, because the default policy key overwrites the policy corresponding to the current URL when the policy-list is configured through the loop.

@Configuration public class CustomPolicy extends DefaultRateLimitKeyGenerator { private final RateLimitProperties properties; private final RateLimitUtils rateLimitUtils; public CustomPolicy(RateLimitProperties properties, RateLimitUtils rateLimitUtils) { super(properties, rateLimitUtils); this.properties = properties; this.rateLimitUtils = rateLimitUtils; } @Override public String key(HttpServletRequest request, Route route, RateLimitProperties. The Policy Policy) {/ / get the current Policy of index int indexOf = properties.getPolicies(route.getId()).indexOf(policy); final List<RateLimitProperties.Policy.Type> types = policy.getType().stream().map(RateLimitProperties.Policy.MatchType::getType).collect(Collectors.toList()); final StringJoiner joiner = new StringJoiner(":");
       joiner.add(properties.getKeyPrefix());
       if(route ! = null) { joiner.add(route.getId()); }if(! types.isEmpty()) {if(types.contains(RateLimitProperties.Policy.Type.URL) && route ! = null) { joiner.add(route.getPath()); }if (types.contains(RateLimitProperties.Policy.Type.ORIGIN)) {
               joiner.add(rateLimitUtils.getRemoteAddress(request));
           }
           if(types.contains(RateLimitProperties.Policy.Type.USER)) { joiner.add(rateLimitUtils.getUser(request)); Joiner. add(string.Valueof (indexOf));returnjoiner.toString(); }}Copy the code

Other traffic limiting configuration items

# redisSpring. Redis. Port = 6379 spring. Redis. Host = 127.0.0.1 spring. Redis. Timeout = 2000# Enable current limiting
zuul.ratelimit.enabled=true
# corresponds to the prefix used to identify the request key
zuul.ratelimit.key-prefix=hello-feign
zuul.ratelimit.repository=redis
# after proxy
zuul.ratelimit.behind-proxy=true
Copy the code