Generally, there are two ways to realize current limiting, token bucket and leaky bucket.
Gold bucket is the number of initialization tokens (containers), which can be passed by taking the token inside. No token can't report an error. You can set the speed and maximum number of tokens to be added to the container
The leaky bucket is to put a request in. When the number of requests reaches the maximum, it will be discarded. The data in the leaky bucket will flow out at a certain speed, otherwise it will not flow out
The gold bucket is realized as follows:
pom
<dependency> <groupId>com.github.vladimir-bukhtoyarov</groupId> <artifactId>bucket4j-core</artifactId> <version>4.0.0</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis-reactive</artifactId> </dependency>
Create the lower class and inherit the lower class
public class LimitFilter implements GatewayFilter, Ordered { private final Logger logger = LoggerFactory.getLogger(LimitFilter.class); int capacity; int refillTokens; Duration refillDuration; public LimitFilter(int capacity, int refillTokens, Duration refillDuration) { this.capacity = capacity; this.refillTokens = refillTokens; this.refillDuration = refillDuration; } private static final Map<String,Bucket> CACHE = new ConcurrentHashMap<>(); private Bucket createNewBucket() { Refill refill = Refill.of(refillTokens,refillDuration); Bandwidth limit = Bandwidth.classic(capacity,refill); return Bucket4j.builder().addLimit(limit).build(); } @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { String ip = exchange.getRequest().getRemoteAddress().getAddress().getHostAddress(); Bucket bucket = CACHE.computeIfAbsent(ip,k -> createNewBucket()); logger.info("IP: " + ip + "ļ¼TokenBucket Available Tokens: " + bucket.getAvailableTokens()); if (bucket.tryConsume(1)) { return chain.filter(exchange); } else { exchange.getResponse().setStatusCode(HttpStatus.TOO_MANY_REQUESTS); return exchange.getResponse().setComplete(); } } @Override public int getOrder() { return 0; } }
Configuration routing
@Bean public RouteLocator customerRouteLocator(RouteLocatorBuilder builder) { // @formatter:off return builder.routes() .route(r -> r.path("/consulserver/**") .filters(f -> f.stripPrefix(1) .filter(new LimitFilter(10,1,Duration.ofSeconds(1)))) .uri("lb://consulserver") .order(0) .id("throttle_customer_service") ).build(); // @formatter:on //Please add Penguin for the source code of social e-commerce platform: //103874626. }