1

Welcome to my GitHub

https://github.com/zq2599/blog_demos

Content: Classification and summary of all original articles and supporting source code, involving Java, Docker, Kubernetes, DevOPS, etc.;

Overview of this article

  • This article is the eighth article in the "Spring Cloud Gateway Actual Combat" series. After the previous study, we have already understood almost the filter. Today, we will complete the last section of the filter: Current Limiter (RequestRateLimiter)
  • The default current limiter is based on redis. The current limit algorithm is the familiar token bucket ( Token Bucket Algorithm ). The principle of token poke will not be expanded here. If you are smart, take a look at the picture below. Understand: The capacity of the bucket to hold tokens is limited, for example, up to 20, and the speed of tokens entering the bucket is constant (note that this is the difference from the leaky bucket algorithm), for example, 10 per second, and each request at the bottom can get an order. The cards will be processed:

在这里插入图片描述

RequestRateLimiter basic routine

  • The steps to use the RequestRateLimiter filter are very simple:
  1. Prepare available redis
  2. Add dependency in maven or gradle<font color="blue">org.springframework.boot:spring-boot-starter-data-redis-reactive</font>
  3. Determine the flow limit according to what dimension, for example, limit the flow according to the username parameter in the request, which is done by writing the implementation of the KeyResolver interface
  4. Configure the application.yml file and add filters
  • The above is the routine of using the RequestRateLimiter filter. Is it simple? Next, let’s code first and then verify

Source download

nameLinkRemark
Project homepagehttps://github.com/zq2599/blog_demosThe project's homepage on GitHub
git warehouse address (https)https://github.com/zq2599/blog_demos.gitThe warehouse address of the source code of the project, https protocol
git warehouse address (ssh)git@github.com:zq2599/blog_demos.gitThe warehouse address of the source code of the project, ssh protocol
  • There are multiple folders in this git project. The source code of this article is under the <font color="blue">spring-cloud-tutorials</font> folder, as shown in the red box below:

在这里插入图片描述

  • There are multiple sub-projects under the <font color="blue">spring-cloud-tutorials</font> folder. The code for this article is <font color="red">gateway-requestratelimiter</font>, as shown in the red box below Shown:

在这里插入图片描述

Ready to work

  • In order to better demonstrate the effect of Gateway, add a web interface to the code (Hello.java) of the service provider <font color="blue">provider-hello</font>, which can accept an input parameter:
    @GetMapping("/userinfo")
    public String userInfo(@RequestParam("username") String username) {
        return Constants.HELLO_PREFIX + " " + username + ", " + dateStr();
    }
  • We will use the above interface for the following test;

coding

  • Add a new sub-project <font color="red">gateway-requestratelimiter</font> under the parent project <font color="blue">spring-cloud-tutorials</font>, and its pom.xml content is as follows, key points Yes <font color="blue">org.springframework.boot:spring-boot-starter-data-redis-reactive</font>:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>spring-cloud-tutorials</artifactId>
        <groupId>com.bolingcavalry</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>gateway-requestratelimiter</artifactId>

    <dependencies>
        <dependency>
            <groupId>com.bolingcavalry</groupId>
            <artifactId>common</artifactId>
            <version>${project.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
        </dependency>
    </dependencies>
</project>
  • In the configuration file application.yml, please pay attention to several parameters of RequestRateLimiter. Detailed comments have been added in Chinese:
server:
  #服务端口
  port: 8081
spring:
  application:
    name: circuitbreaker-gateway
  # redis配置
  redis:
    host: 192.168.50.43
    port: 6379

  cloud:
    gateway:
      routes:
        - id: path_route
          uri: http://127.0.0.1:8082
          predicates:
            - Path=/hello/**
          filters:
            - name: RequestRateLimiter
              args:
                  # 令牌入桶的速度为每秒100个,相当于QPS
                redis-rate-limiter.replenishRate: 100
                # 桶内能装200个令牌,相当于峰值,要注意的是:第一秒从桶内能去200个,但是第二秒只能取到100个了,因为入桶速度是每秒100个
                redis-rate-limiter.burstCapacity: 200
                # 每个请求需要的令牌数
                redis-rate-limiter.requestedTokens: 1
  • The code CustomizeConfig.java that specifies the current limiting dimension, here is to limit the current according to the value of the request parameter <font color="blue">username</font>, assuming that half of the requested username in the real request is equal to <font color=" red">Tom</font>, the other half of the username is equal to <font color="red">Jerry</font>, according to the configuration of application.yml, Tom’s request QPS is 10, and Jerry’s QPS is also 10:
package com.bolingcavalry.gateway.config;

import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import reactor.core.publisher.Mono;
import java.util.Objects;

@Configuration
public class CustomizeConfig {
    @Bean
    KeyResolver userKeyResolver() {
        return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("username"));
    }
}
  • The no-nutrient startup class RequestRateLimiterApplication.java:
package com.bolingcavalry.gateway;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class RequestRateLimiterApplication {
    public static void main(String[] args) {
        SpringApplication.run(RequestRateLimiterApplication.class,args);
    }
}
  • After the code is written, the verification begins;

Verification (the bucket capacity is equal to the speed of entering the bucket)

  • The first thing to verify is the effect when the bucket capacity is equal to the bucket entry speed. Please modify the application.yml file of the <font color="blue">gateway-requestratelimiter</font> application to make redis-rate-limiter.replenishRate and redis- The value of rate-limiter.burstCapacity is equal to 100, which means that the size of the bucket is equal to 100, and the number of tokens placed per second is also 100
  • Make sure that redis has been started and kept with the configuration in application.yml
  • Start nacos (provider-hello dependency)
  • Start the service provider <font color="blue">provider-hello</font>
  • Start <font color="blue">gateway-requestratelimiter</font>
  • In order to simulate web requests, I used <font color="blue">Apache Benchmark</font>, the download link of the windows version:
    https://www.apachelounge.com/download/VS16/binaries/httpd-2.4.48-win64-VS16.zip
  • After downloading and decompressing the above file, you can use it. After entering <font color="blue">Apache24\bin</font> in the console, execute the following command, which means to send 10,000 requests to the specified address, and the number of concurrent is 2:
ab -n 10000  -c 2 http://localhost:8081/hello/userinfo?username=Tom
  • The console output is as follows. It can be seen that in less than eight seconds, only 800 succeeded, which proves that the current limit is in line with expectations:

在这里插入图片描述

Verification (the capacity of the bucket is greater than the speed of entering the bucket)

  • Next, try the current limiting effect when the barrel capacity is greater than the barrel entering speed, which has an important reference value for us to control the peak response.
  • Please modify the file in application.yml of the <font color="blue">gateway-requestratelimiter</font> application, redis-rate-limiter.replenishRate keeps <font color="blue"> 100 </font> unchanged , But redis-rate-limiter.burstCapacity is changed to <font color="red"> 200 </font>, which means that the number of tokens inserted per second is still 100, but the bucket capacity has doubled
  • Restart the application<font color="blue">gateway-requestratelimiter</font>
  • Execute the following command again, which means to send 10,000 requests to the specified address, and the concurrent number is 2:
ab -n 10000  -c 2 http://localhost:8081/hello/userinfo?username=Tom
  • The test result is as shown in the figure below. It can be seen that it is in line with expectations, and all tokens in the bucket can be used up to support scenarios where the peak value exceeds QPS:

在这里插入图片描述

Verification (Limit flow based on the dimension of username)

  • Next, verify the dimensions of the current limit, whether the current limit is based on the value of the request parameter username
  • Let's open two command lines and send the request at the same time (the action should be fast), the username of the first is equal to <font color="blue">Tom</font>, and the second is equal to <font color="blue">Jerry< /font>, theoretically, if it is completed within 8 seconds, then each command has 900 requests to succeed
  • The test result is as shown in the figure below. It can be seen that it is in line with expectations, and each username uses its own token:

在这里插入图片描述

  • So far, the Spring Cloud Gateway current limiting actual combat has been completed, such a simple and easy-to-use current limiting solution, hope to bring you reference for your study and use

You are not lonely, Xinchen is with you all the way

  1. Java series
  2. Spring series
  3. Docker series
  4. kubernetes series
  5. database + middleware series
  6. DevOps series

Welcome to pay attention to the public account: programmer Xin Chen

Search "Programmer Xin Chen" on WeChat, I am Xin Chen, and I look forward to traveling the Java world with you...
https://github.com/zq2599/blog_demos

程序员欣宸
147 声望24 粉丝

热爱Java和Docker