令牌桶限流

概要

  • 在项目中引入Guava相关包
  • 创建拦截器
  • 添加拦截器
  • 测试

1.在项目中引入Guava相关包

    <dependency>
        <groupId>com.google.guava</groupId>
        <artifactId>guava</artifactId>
        <version>23.5-jre</version>
    </dependency>

2.创建拦截器

public class AuthInterceptor extends HandlerInterceptorAdapter {

    enum LimiterTypeEnum {
        DROP,//丢弃
        WAIT //等待
    }


    //限流器
    private RateLimiter rateLimiter;
    //限流类型
    private LimiterTypeEnum limiterType;

    /**
     * @param permitsPerSecond 限流量 (每秒处理量)
     * @param limiterType      限流类型
     */
    public AuthInterceptor(int permitsPerSecond, LimiterTypeEnum limiterType) {
        this.rateLimiter = RateLimiter.create(permitsPerSecond);
        this.limiterType = limiterType;
    }

    /**
     * @param permitsPerSecond 每秒新增的令牌数(这个是平滑增长,有一个预热过程)
     * @param limiterType      限流类型
     */
    public AuthInterceptor(double permitsPerSecond, LimiterTypeEnum limiterType) {
        this.rateLimiter = RateLimiter.create(permitsPerSecond, 1, TimeUnit.SECONDS);
        this.limiterType = limiterType;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        if (Objects.equals(limiterType, LimiterTypeEnum.DROP)) {
            return rateLimiter.tryAcquire(); //false为被限流
        } else {
            rateLimiter.acquire();//一直等待,直到拿到令牌
            return true;
        }
    }

}

3.添加拦截器

@Configuration
public class AuthHandlerAdapter extends WebMvcConfigurerAdapter {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new AuthInterceptor(10, AuthInterceptor.LimiterTypeEnum.DROP))
                .addPathPatterns("/*");
    }
}

4.测试

  • controller

    @RestController
    public class TestController {
    
        @GetMapping
        public String TestGetString() {
            return "爱生活,爱java";
        }
    }
    
  • 并发请求

     public class RequestTest {
         public static void main(String[] args) {
             HttpClient httpClient = new HttpClient("http://127.0.0.1:8080", 2000, 2000);
             IntStream.range(0, 1000).forEach(value -> {
                 testSend(httpClient);
                 try {
                     TimeUnit.MILLISECONDS.sleep(100);
                 } catch (InterruptedException e) {
                     e.printStackTrace();
                 }
     
             });
     
         }
         public static void testSend(HttpClient httpClient) {
             try {
                 httpClient.sendGet("UTF-8");
             } catch (Exception e) {
                 e.printStackTrace();
             }
         }
     }
    
posted @ 2021-01-27 15:49  qiudx  阅读(32)  评论(0)    收藏  举报