2021-9-15 gateway current limiting

Keywords: Java

As we said before, the gateway can do a lot of things, such as flow restriction. When our system is frequently requested, it may crush the system. Therefore, in order to solve this problem, we need to do flow restriction in each micro service. However, if there is a gateway, we can do flow restriction in the gateway system, Because all requests need to pass through the gateway system before they can be routed to the microservice.

2.1 train of thought analysis

2.2 token bucket algorithm

Token bucket algorithm is one of the common flow limiting algorithms. It is roughly described as follows: 1) all requests need to get an available token before processing; 2) Add tokens to the bucket at a certain rate according to the current limit; 3) The bucket sets the maximum token placement limit. When the bucket is full, the newly added token is discarded or rejected; 4) After the request is reached, first obtain the token in the token bucket, and then carry out other business logic with the token. After processing the business logic, delete the token directly; 5) The token bucket has a minimum limit. When the token in the bucket reaches the minimum limit, the token will not be deleted after the request is processed, so as to ensure sufficient current limit

As shown below:

There are many technologies for the implementation of this algorithm. Guava (pronunciation: wow) is one of them, and redis client also has its implementation.

2.3 implementation of gateway current limiting code

Requirement: each ip address can only send one request within one second, and the extra requests return 429 error.

Code implementation:

Code implementation:

(1)spring cloud gateway Default use redis of RateLimter Current limiting algorithm. So we need to first introduce redis Dependence of

<!--redis-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
    <version>2.1.3.RELEASE</version>
</dependency>
(2)definition KeyResolver

stay GatewayApplicatioin Add the following code to the boot class, KeyResolver Used to calculate the current limit of a certain type KEY That is, you can KeyResolver To specify the current limiting Key. 

    //Define a KeyResolver
    @Bean
    public KeyResolver ipKeyResolver() {
        return new KeyResolver() {
            @Override
            public Mono<String> resolve(ServerWebExchange exchange) {
                return Mono.just(exchange.getRequest().getRemoteAddress().getHostName());
            }
        };
    }
(3)modify application.yml The configuration item in specifies the configuration of limiting traffic, and REDIS The final configuration after modification is as follows:

spring:
  application:
    name: sysgateway
  cloud:
    gateway:
      globalcors:
        cors-configurations:
          '[/**]': # Match all requests
            allowedOrigins: "*" #Cross domain processing allows all domains
            allowedMethods: # Supported methods
            - GET
            - POST
            - PUT
            - DELETE
      routes:
      - id: goods
        uri: lb://goods
        predicates:
        - Path=/goods/**
        filters:
        - StripPrefix= 1
        - name: RequestRateLimiter #The request stream name cannot be written casually 
          args:
            key-resolver: "#{@ipKeyResolver}"
            redis-rate-limiter.replenishRate: 1 #Average rate of token bucket population per second
            redis-rate-limiter.burstCapacity: 1 #Total token bucket capacity
      - id: system
        uri: lb://system
        predicates:
        - Path=/system/**
        filters:
        - StripPrefix= 1
  # Redis 127.0.0.1 configuration can be omitted
  redis:
    host: 192.168.200.128
    port: 6379
server:
  port: 9101
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:6868/eureka
  instance:
    prefer-ip-address: true

Explanation:

Burst capacity: total capacity of token bucket.
replenishRate: average rate of token bucket population per second.
Key resolver: the name of the Bean object of the parser for the current limiting key. It uses a SpEL expression to get the Bean object from the Spring container according to #{@ beanName}.

Stable rate burstCapacity is achieved by setting the same value in replenishRate and. When burstCapacity is set higher than, temporary burst replenishRate can be allowed. In this case, the rate limiter needs to be allowed for a period of time between bursts (according to replenishRate), because two consecutive bursts will cause the request to be discarded (HTTP 429 - Too Many Requests)

Key resolver: "#{@ userKeyResolver}" is used to specify which KeyResolver to use through SPEL expression

Configured as above:

Indicates that a request is allowed to pass in one second, and the filling rate of the token bucket is also one token added in one second.

The maximum emergency condition only allows one request per second, which can be adjusted according to the service.

(4) Testing

Start redis

Start registry

Start commodity micro service

Start the gateway

Open browser http://localhost:9101/goods/brand

Fast refresh. When multiple requests are sent within 1 second, 429 error will be returned.

Posted by Zeceer on Sun, 19 Sep 2021 04:13:15 -0700