zoukankan      html  css  js  c++  java
  • 限流算法

    限流算法--Google的Guava令牌桶

    pom依赖

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

    速率限制器 RateLimiter

    /**
     * 创建一个限速器,每1秒,产生2.5个令牌 
     */
    RateLimiter rateLimiter = RateLimiter.create(2.5, 1, TimeUnit.SECONDS);
     
    /**
     * 尝试获取1个令牌,如果没有,会阻塞当前线程。直到获取成功返回。
     * 返回值是,阻塞的秒数
     */
    double waitSeconds = rateLimiter.acquire();
     
    /**
     * 尝试获取1个令牌,不会阻塞当前线程。
     * 立即返回是否获取成功。
     */
    boolean success = rateLimiter.tryAcquire();

    重载方法

    不论是阻塞获取令牌还是非阻塞获取令牌,它们都有几个重载方法。一看也清楚,就是可以设置获取令牌的数量,以及阻塞的时间

    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)

    拦截器

    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;
     
     /**
      * 通过构造函数初始化限速器
      */
     public RateLimiterInterceptor(RateLimiter rateLimiter) {
      super();
      this.rateLimiter = rateLimiter;
     }
     
     @Override
     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
      
      if(this.rateLimiter.tryAcquire()) {
       /**
        * 成功获取到令牌
        */
       return true;
      }
     
      /**
       * 获取失败,直接响应“错误信息”
       * 也可以通过抛出异常,通过全全局异常处理器响应客户端
       */
      response.setCharacterEncoding(StandardCharsets.UTF_8.name());
      response.setContentType(MediaType.TEXT_PLAIN_VALUE);
      response.getWriter().write("服务器繁忙");
      return false;
     }
    }

    拦截器的配置类

    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接口,1秒钟生成1个令牌,也就是1秒中允许一个人访问
       */
      registry.addInterceptor(new RateLimiterInterceptor(RateLimiter.create(1, 1, TimeUnit.SECONDS)))
       .addPathPatterns("/test");
     }
     
    }

    限流算法--漏桶算法

      漏桶算法这个名字就很形象,算法内部有一个容器,类似生活用到的漏斗,当请求进来时,相当于水倒入漏斗,然后从下端小口慢慢匀速的流出。不管上面流量多大,下面流出的速度始终保持不变。不管服务调用方多么不稳定,通过漏桶算法进行限流,每10毫秒处理一次请求。因为处理的速度是固定的,请求进来的速度是未知的,可能突然进来很多请求,没来得及处理的请求就先放在桶里,既然是个桶,肯定是有容量上限,如果桶满了,那么新进来的请求就丢弃

    限流算法--计数器算法

      确定方法的最大访问量MAX,每次进入方法前计数器+1,将结果和最大并发量MAX比较,如果大于等于MAX,则直接返回;如果小于MAX,则继续执行

    限流算法--并发量算法

      确定方法的最大并发量MAX,每次进入方法前计数器+1,将结果和最大并发量MAX比较,如果大于等于MAX,则直接返回;如果小于MAX,则继续执行;退出方法后计数器-1。
    比如限制服务的并发访问数是100,而服务处理的平均耗时是10毫秒,那么1分钟内,该服务平均能提供( 1000 / 10 ) * 60 * 100 = 6000 次

    限流算法--滑动窗口等算法

    不积跬步,无以至千里;不积小流,无以成江海
  • 相关阅读:
    Java利用Base64编码和解码图片文件
    SQL查询结果列拼接成逗号分隔的字符串:group_concat
    两个正则表达式:匹配固定电话号码,匹配手机号码
    IDEA导入Junit jar包,在JavaSE的Module中使用Junit测试
    如何正确遍历删除List中的元素(普通for循环、增强for循环、迭代器iterator、removeIf+方法引用)
    Java Springboot 根据图片链接生成图片下载链接 及 多个图片打包zip下载链接
    fastjson List<> 转Json , Json 转List<>
    PHP结合memcacheq消息队列解决并发问题
    Redis与Memcached的区别
    yii2 中excel表导出
  • 原文地址:https://www.cnblogs.com/hzzjj/p/15782768.html
Copyright © 2011-2022 走看看