Limit the flow said in detail, the hall is also more. This algorithm that algorithm, this strategy that strategy. There is no absolute silver bullet. Should be combined with the actual scene to achieve. The simplest, using Google’s Guava, a few lines of code. You can elegantly limit traffic on an interface.

Token bucket algorithm

The popular understanding is that there is a fixed size bucket, the tap has been a certain frequency of water into the water. When the water is full, it stops dripping. Before making a request, the client tries to take at least one drop of water out of the bucket. Because the size of the bucket is fixed, the tap water frequency is fixed. Thus, the data interface access traffic is guaranteed.

Guava

Google tools library, contains a large number of Java utility classes, like hash algorithms, string manipulation, collections, etc…

Github.com/google/guav…

<! -- https://mvnrepository.com/artifact/com.google.guava/guava --> <dependency> <groupId>com.google.guava</groupId> < artifactId > guava < / artifactId > < version > 29.0 jre < / version > < / dependency >Copy the code

RateLimiter RateLimiter

/** * Create a speed limiter that generates 2.5 tokens */ every 1 second
RateLimiter rateLimiter = RateLimiter.create(2.5.1, TimeUnit.SECONDS);

/** * attempts to obtain 1 token, if not, blocks the current thread. Until it returns on success. The return value is the number of seconds of blocking */
double waitSeconds = rateLimiter.acquire();

/** * Attempts to obtain 1 token without blocking the current thread. * Returns immediately whether the command succeeded. * /
boolean success = rateLimiter.tryAcquire();
Copy the code

Okay, so that’s the core code. Just 3 rows. Start by creating a speed limiter that specifies the token production frequency. There are two core methods, blocking and non-blocking token acquisition. The code is also easy to understand.

Overloaded methods

Both blocking and non-blocking token retrieval have several overloaded methods. You can set the number of tokens to obtain and the duration of blocking.

public double acquire(int permits)

public boolean tryAcquire(Duration timeout)
public boolean tryAcquire(int permits)
public boolean tryAcquire(long timeout, TimeUnit unit)
public boolean tryAcquire(int permits, long timeout, TimeUnit unit) 
public boolean tryAcquire(int permits, Duration timeout)
Copy the code

A Controller is a limited interface

@RestController
@RequestMapping("/test")
public class TestController {
	
	@GetMapping
	public Object test (a) {
		return Collections.singletonMap("success"."true"); }}Copy the code

RateLimiterInterceptor, which implements the speed limiting logic

import java.nio.charset.StandardCharsets;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.http.MediaType;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import com.google.common.util.concurrent.RateLimiter;

public class RateLimiterInterceptor extends HandlerInterceptorAdapter {

	private final RateLimiter rateLimiter;

	/** * Initializes the limiter via the constructor */
	public RateLimiterInterceptor(RateLimiter rateLimiter) {
		super(a);this.rateLimiter = rateLimiter;
	}

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
		
		if(this.rateLimiter.tryAcquire()) {
			/** * Successfully obtained the token */
			return true;
		}

		/** * can respond directly to "error message" by throwing an exception, through the global exception handler to respond to the client */
		response.setCharacterEncoding(StandardCharsets.UTF_8.name());
		response.setContentType(MediaType.TEXT_PLAIN_VALUE);
		response.getWriter().write("Server busy");
		return false; }}Copy the code

Configuration of interceptors

import java.util.concurrent.TimeUnit;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import com.google.common.util.concurrent.RateLimiter;

import io.springboot.jwt.web.interceptor.RateLimiterInterceptor;


@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {
	
	@Override
	public void addInterceptors(InterceptorRegistry registry) {
		/** * test interface, generates 1 token in 1 second, i.e. allows one person to access */ in 1 second
		registry.addInterceptor(new RateLimiterInterceptor(RateLimiter.create(1.1, TimeUnit.SECONDS)))
			.addPathPatterns("/test"); }}Copy the code

The client demonstrates the flow limiting effect


Original text: springboot. IO/topic / 235 / t…