AOP+ RateLimiter单机限流

2020-06-13  本文已影响0人  香沙小熊

1.添加依赖

            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-aop</artifactId>
            </dependency>

启动类上添加注解

@EnableAspectJAutoProxy(proxyTargetClass=true)

2.AOP类

/**
 * @author xionghu
 * @date 2020/6/13 10:32
 * @desc 配置限流切面
 */
@Aspect
@Scope
@Component
public class RateLimiterAspect {
    private static final Logger log = LoggerFactory.getLogger(RateLimiterAspect.class);
    private final ConcurrentMap<String, RateLimiter> RATE_LIMITER_CACHE = new ConcurrentHashMap<>();

    @Pointcut(value = "@annotation(com.ihuaben.bridge.web.ratelimiter.ApiRateLimiter)")
    public void rateLimit() {

    }

    @Around("rateLimit()")
    public Object pointcut(ProceedingJoinPoint point) throws Throwable {
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();
        // 通过 AnnotationUtils.findAnnotation 获取 RateLimiter 注解
        ApiRateLimiter rateLimiter = AnnotationUtils.findAnnotation(method, ApiRateLimiter.class);

        if (rateLimiter == null) {
            return point.proceed();
        }
        if (rateLimiter.qps() > ApiRateLimiter.NOT_LIMITED) {
            double qps = rateLimiter.qps();
            if (RATE_LIMITER_CACHE.get(method.getName()) == null) {
                // 初始化 QPS
                RATE_LIMITER_CACHE.put(method.getName(), RateLimiter.create(qps));
            }

            log.debug("[{}]的QPS设置为: {}", method.getName(), RATE_LIMITER_CACHE.get(method.getName()).getRate());
            // 尝试获取令牌
            if (RATE_LIMITER_CACHE.get(method.getName()) != null && !RATE_LIMITER_CACHE.get(method.getName()).tryAcquire(rateLimiter.timeout(), rateLimiter.timeUnit())) {
                throw new BusinessException(EmBusinessError.RATELIMIT);
            }
        }
        return point.proceed();
    }

}
import org.springframework.core.annotation.AliasFor;
import java.lang.annotation.*;
import java.util.concurrent.TimeUnit;
/**
 * @author xionghu
 * @date 2020/6/13 10:32
 * @desc 创建限流限制
 */
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ApiRateLimiter {


    int NOT_LIMITED = 0;

    /**
     * qps
     */
    @AliasFor("qps") double value() default NOT_LIMITED;

    /**
     * qps
     */
    @AliasFor("value") double qps() default NOT_LIMITED;

    /**
     * 超时时长
     * 默认间隔1s时间
     */
    int timeout() default 1000;

    /**
     * 超时时间单位
     */
    TimeUnit timeUnit() default TimeUnit.MILLISECONDS;
}

3.AOP类

@RestController
@RequestMapping({ "/admin" })
public class TestController extends BaseController {

    @RequestMapping({ "/hello" })
    @ApiRateLimiter(value = 5)
    public ResponseEntity hello(String name) {
        System.out.println("................");
        return buildResponseEntity("word","hello " + name);
    }

    @RequestMapping({ "/Permission" })
    public ResponseEntity Permission(String name) {
        return buildResponseEntity("word","Permission " + name);
    }
}

限制1秒钟 只能 有五个请求才能走方法

验证
image.png
注意:@ApiRateLimiter(value = ) 根据业务需要设定相应的值
上一篇 下一篇

猜你喜欢

热点阅读