About the pig:

Based on Spring Cloud and oAuth2.0, the development platform is based on the separation of Vue before and after, supporting accounts, SMS, SSO and other logins, and providing supporting video development tutorials.

Code cloud Address:gitee.com/log4j/pig

About Spring Cloud Gateway

SpringCloudGateway is an official gateway developed by Spring based on Spring 5.0, Spring Boot 2.0, and Project Reactor technologies. SpringCloudGateway aims to provide a simple and effective way to route apis. As a Gateway in the Spring Cloud ecosystem, Spring Cloud Gateway aims to replace Netflix ZUUL. It not only provides a unified routing mode, but also provides basic Gateway functions based on Filter chain, such as security, monitoring/burying point, and flow limiting.

How does Zuul implement multi-dimensional traffic limiting please refer to my blog

Zuul: Multi-dimensional traffic limiting for building high availability gateways

The Gateway traffic limiting starts

POM depends on

<! - spring cloud gateway rely on - > < the 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>Copy the code

Configure traffic limiting by requested IP address

spring:
  cloud:
    gateway:
      routes:
      - id: requestratelimiter_route
        uri: lb://pigx-upms
        order: 10000
        predicates:
        - Path=/admin/**
        filters:
        - name: RequestRateLimiter
          args:
            redis-rate-limiter.replenishRate: 1  The volume of the token bucket
            redis-rate-limiter.burstCapacity: 3  # Flow rate per second
            key-resolver: "#{@remoteAddrKeyResolver}" #SPEL expression to the corresponding bean
        - StripPrefix=1
Copy the code

Configure bean, multi-dimensional traffic limiting entry

*/ @bean KeyResolver */ @bean KeyResolver */remoteAddrKeyResolver() {
    return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostName());
}
Copy the code

OK to complete.

Pressure test

Concurrent 5 threads.

Redis data changes

We use the monitor command of Redis to check the operation of Redis in real time. You will find that two keys are operated on in Redis

  • request_rate_limiter.{xxx}.timestamp
  • request_rate_limiter.{xxx}.tokens

Realize the principle of

The Spring Cloud Gateway implements Redis limiting by default, if the extension only needs to implement the Ratelimter interface.

RedisRateLimter core code, determine whether to take the token implementation, by calling redis LUA script.

public Mono<Response> isAllowed(String routeId, String id) {
	Config routeConfig = getConfig().getOrDefault(routeId, defaultConfig);
	int replenishRate = routeConfig.getReplenishRate();
	int burstCapacity = routeConfig.getBurstCapacity();

	try {
		List<String> keys = getKeys(id);
		returns unixtime in seconds.
		List<String> scriptArgs = Arrays.asList(replenishRate + "", burstCapacity + "",
				Instant.now().getEpochSecond() + ""."1"); // Here is the core, executing the LUA script of Redis. Flux<List<Long>> flux = this.redisTemplate.execute(this.script, keys, scriptArgs);return flux.onErrorResume(throwable -> Flux.just(Arrays.asList(1L, -1L)))
				.reduce(new ArrayList<Long>(), (longs, l) -> {
					longs.addAll(l);
					return longs;
				}) .map(results -> {
					boolean allowed = results.get(0) == 1L;
					Long tokensLeft = results.get(1);

					Response response = new Response(allowed, getHeaders(routeConfig, tokensLeft));

					if (log.isDebugEnabled()) {
						log.debug("response: " + response);
					}
					return response;
				});
	}
	catch (Exception e) {
		log.error("Error determining if user allowed from redis", e);
	}
	return Mono.just(new Response(true, getHeaders(routeConfig, -1L)));
}
Copy the code

The LUA script