Reprinted from: https://www.jianshu.com/p/2fc92a929e8e
Narration
In order to prevent the API without token access from being called infinitely, some services need to be API restricted. It's like taking some interfaces for registration or sending verification codes. If they are called maliciously and infinitely, they will cause some expenses. Sending SMS or e-mail are all third-party interfaces. The more times they are used, the more expenses they will incur, which will directly lead to service crash. It is necessary to introduce current limiting configuration in spring cloud API gateway.
Solution
The dependence of Zuul RateLimit in pom file
<dependency> <groupId>com.marcosbarbero.cloud</groupId> <artifactId>spring-cloud-zuul-ratelimit</artifactId> <version>1.3.2.RELEASE</version> </dependency>
yml configuration
//A more detailed explanation of the configuration is written below. Here is just a simple configuration. The following configuration can restrict the flow of services zuul: routes: Your routing configuration test: path: serviceId: ratelimit: enabled: true policies: test: Routing name limit: Restriction times refresh-interval: Refresh time type: type
List
Locally configure one of your own services to access the API of the service only ten times in a minute. If it is more than ten times, the gateway will report an error
zuul: routes: test: path: /api/test/** serviceId: hscf-cloud-test-9457 ratelimit: enabled: true policies: test: limit: 10 refresh-interval: 60 type: origin Current limiting mode
Let's briefly analyze the source code
The RateLimit class inherits ZuulFilter, and the variables in it are the property values we configured in the yml file. Part of the source code in RateLimit. If the filterType is "pre", it means to intercept before each API access. The three variables, LIMIT_HEADER, warning_header, and RESET_HEADER, should be to obtain the number of accesses we have configured, and record the number of accesses remaining in the time.
public class RateLimitFilter extends ZuulFilter { public static final String LIMIT_HEADER = "X-RateLimit-Limit"; public static final String REMAINING_HEADER = "X-RateLimit-Remaining"; public static final String RESET_HEADER = "X-RateLimit-Reset"; public String filterType() { return "pre"; } public int filterOrder() { return -1; } public boolean shouldFilter() { return this.properties.isEnabled() && this.policy(this.route()).isPresent(); }
Judgment is made in the main logic run(). First, use this.policy(route).ifPresent((policy) to determine whether the policy configuration information exists. If it exists, it will be read
Take the current limit value, return the remaining limit value, and finally determine whether the remaining limit value is less than 0. If it is less than 0, too many exceptions will be reported
TOO_MANY_REQUESTS(429, "Too Many Requests")
public Object run() { RequestContext ctx = RequestContext.getCurrentContext(); HttpServletResponse response = ctx.getResponse(); HttpServletRequest request = ctx.getRequest(); Route route = this.route(); this.policy(route).ifPresent((policy) -> { String key = this.rateLimitKeyGenerator.key(request, route, policy); Rate rate = this.rateLimiter.consume(policy, key); response.setHeader("X-RateLimit-Limit", policy.getLimit().toString()); response.setHeader("X-RateLimit-Remaining", String.valueOf(Math.max(rate.getRemaining().longValue(), 0L))); response.setHeader("X-RateLimit-Reset", rate.getReset().toString()); if(rate.getRemaining().longValue() < 0L) { ctx.setResponseStatusCode(HttpStatus.TOO_MANY_REQUESTS.value()); ctx.put("rateLimitExceeded", "true"); throw new ZuulRuntimeException(new ZuulException(HttpStatus.TOO_MANY_REQUESTS.toString(), HttpStatus.TOO_MANY_REQUESTS.value(), (String)null)); } }); return null; } . . . . . .
Exception information of the console. The exception code is 429, that is, too many requests: too many requests (429, "too many requests")
Detailed configuration information interpretation of RateLimit
zuul: ratelimit: key-prefix: your-prefix #Prefix corresponding to the key used to identify the request enabled: true repository: REDIS #Corresponding storage type (used to store Statistics) behind-proxy: true #After agency default-policy: #Optional - policies configured for all routes, unless policies is specifically configured limit: 10 #Optional - limit on the number of requests per refresh window quota: 1000 #Optional - request time limit per refresh time window (seconds) refresh-interval: 60 # Refresh time window time, default (seconds) type: #Optional current limiting mode - user - origin - url policies: myServiceId: #Specific routes limit: 10 #Optional - limit on the number of requests per refresh window quota: 1000 #Optional - request time limit per refresh time window (seconds) refresh-interval: 60 # Refresh time window time, default (seconds) type: #Optional current limiting mode - user - origin - url
- url type flow restriction is distinguished by request path
- origin is distinguished by client IP address
- Users are distinguished by login user names, including anonymous users