Home > Java > javaTutorial > Interface current limiting, all cool operations are here!

Interface current limiting, all cool operations are here!

Release: 2023-07-26 14:22:33
forward
1162 people have browsed it

Why current limiting

When designing the system, we will have an estimated capacity of the system, which exceeds the TPS/QPS that the system can withstand for a long time. threshold, the system may be overwhelmed, eventually causing the entire service to become unavailable. In order to avoid this situation, we need to limit the flow of interface requests.

So, we can protect the system or avoid unnecessary waste of resources by limiting the rate of concurrent access requests or the number of requests within a time window. Once the rate limit is reached, service can be denied. Queue or wait.

Current limiting background

The system has an interface for obtaining mobile phone SMS verification codes. Because it is an open interface, in order to prevent users from constantly sending Request to obtain the verification code to prevent malicious interface brushing, so the simplest counter method is used to limit the current, limiting each IP to only one request per minute, and then the time window limit for each other mobile phone number is through the business Make judgments logically. Generally, some interfaces have a relatively large number of visits and may overwhelm the system, so traffic restrictions need to be added! Such as: flash sale, etc...

Implementation method

##1.Introduce dependencies
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
Copy after login

2. Custom current limiting annotation
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RateLimiter {
    /**
     * 限流key
     */
     String key() default Constants.RATE_LIMIT_KEY;

    /**
     * 限流时间,单位秒
     */
     int time() default 60;

    /**
     * 限流次数
     */
    int count() default 100;

    /**
     * 限流类型
     */
    LimitType limitType() default LimitType.DEFAULT;

    /**
     * 限流后返回的文字
     */
    String limitMsg() default "访问过于频繁,请稍候再试";
}
Copy after login

3. Current limiting aspect
@Aspect
@Component
public class RateLimiterAspect {

    private final static Logger log = LoggerFactory.getLogger(RateLimiterAspect.class);

    @Autowired
    private RedisUtils redisUtils;

    @Before("@annotation(rateLimiter)")
    public void doBefore(JoinPoint point, RateLimiter rateLimiter) throws Throwable {
        int time = rateLimiter.time();
        int count = rateLimiter.count();
        long total = 1L;

        String combineKey = getCombineKey(rateLimiter, point);
        try
        {
            if(redisUtils.hasKey(combineKey)){
                total = redisUtils.incr(combineKey,1);  //请求进来,对应的key加1
                if(total > count)
                    throw new ServiceRuntimeException(rateLimiter.limitMsg());
            }else{
                redisUtils.set(combineKey,1,time);  //初始化key
            }
        }
        catch (ServiceRuntimeException e)
        {
            throw e;
        }
        catch (Exception e)
        {
            throw new ServiceRuntimeException("网络繁忙,请稍候再试");
        }
    }

    /**
     * 获取限流key
     * @param rateLimiter
     * @param point
     * @return
     */
    public String getCombineKey(RateLimiter rateLimiter, JoinPoint point) {
        StringBuffer stringBuffer = new StringBuffer(rateLimiter.key());
        if (rateLimiter.limitType() == LimitType.IP)
        {
            stringBuffer.append(IpUtils.getIpAddr(ServletUtils.getRequest())).append("-");
        }
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();
        Class<?> targetClass = method.getDeclaringClass();
        stringBuffer.append(targetClass.getName()).append("-").append(method.getName());
        return stringBuffer.toString();
    }

}
Copy after login

4. Write A simple interface for testing
@RestController
public class TestController {

    @RateLimiter(time = 60, count = 1, limitType = LimitType.IP, limitMsg = "一分钟内只能请求一次,请稍后重试")
    @GetMapping("/hello")
    public ResultMsg hello() {
        return ResultMsg.success("Hello World!");
    }
}
Copy after login

##5. Global exception interception
@RestControllerAdvice
public class GlobalExceptionHandler {
    private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    /**
     * 业务异常
     */
    @ExceptionHandler(ServiceRuntimeException.class)
    public ResultMsg handleServiceException(ServiceRuntimeException e, HttpServletRequest request)
    {
        return ResultMsg.error(e.getMessage());
    }

    /**
     * 系统异常
     */
    @ExceptionHandler(Exception.class)
    public ResultMsg handleException(Exception e, HttpServletRequest request)
    {
        return ResultMsg.error("系统异常");
    }

}
Copy after login

6. Interface test

1) The first time sent, the result is returned normally

Interface current limiting, all cool operations are here!

2) The second time sent within one minute, an error is returned, and the current limit prompt

Interface current limiting, all cool operations are here!

The above is the AOP Redis solution to implement interface current limiting. Have you given up on it?

There are other current limiting methods, such as sliding window current limiting method (more rigorous than counter), token bucket, etc... Interested friends can learn about it.


The above is the detailed content of Interface current limiting, all cool operations are here!. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:Java学习指南
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template