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.