美文网首页
基于信号量和令牌桶算法的限流

基于信号量和令牌桶算法的限流

作者: fantuanjiaozi | 来源:发表于2018-08-16 14:22 被阅读371次

限流的三种算法

限流主要有三种算法:信号量、漏桶算法和令牌桶算法。

信号量限制的是并发、资源。令牌桶限制的是QPS。

信号量

Semaphore是一个计数信号量。常用于限制获取某资源的线程数量,可基于java的concurrent并发包实现。
通过acquire()方法获取许可,该方法会阻塞,直到获取许可为止。
通过release()方法释放许可。

基于java的concurrent的实现


@RestController
@RequestMapping("/semaphore")
public class SemaphoreController {
    //初始化信号量=5,true-公平信号量FIFO。
    private Semaphore semaphore = new Semaphore(5, true);

    @RequestMapping("/acquire/{par1}")
    public String acquire(@PathVariable String par1){
        try {
            semaphore.acquire(1);//获取一个许可
            //do sth
            return par1+"获取一个许可";
        }catch (InterruptedException e){
            e.printStackTrace();
            return "获取许可失败";
        }catch (Exception e1){
            return "获取许可失败";
        }finally {
            semaphore.release(1);//处理完后,释放一个许可
        }
    }
}

漏桶算法

漏桶(Leaky Bucket)算法思路很简单,水(请求)先进入到漏桶里,漏桶以一定的速度出水(接口有响应速率),当水流入速度过大会直接溢出(访问频率超过接口响应速率),然后就拒绝请求,可以看出漏桶算法能强行限制数据的传输速率.示意图如下:

漏桶.jpg

令牌桶算法

令牌桶算法(Token Bucket)和 Leaky Bucket 效果一样但方向相反的算法,更加容易理解.随着时间流逝,系统会按恒定1/QPS时间间隔(如果QPS=100,则间隔是10ms)往桶里加入Token(想象和漏洞漏水相反,有个水龙头在不断的加水),如果桶已经满了就不再加了.新请求来临时,会各自拿走一个Token,如果没有Token可拿了就阻塞或者拒绝服务

令牌桶.jpg

令牌桶算法比漏桶算法更加优雅,适合秒杀等场景。本示例主要描述基于google的guava令牌桶算法的实现。

pom坐标,建议使用16.0及以上版本

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

限流实现

@RestController
@RequestMapping("/ratelimiter")
public class RateLimiterController {

    private RateLimiter rateLimiter = RateLimiter.create(0.5);//每秒发放0.5个令牌。注意:本初始化声明不要放在方法内

    //非阻塞机制
    @RequestMapping("/nonblock")
    public String rateLimiterNonBlock() {
        //如果令牌桶内有令牌,则直接发放;如果能在1000ms内能够获取一个令牌,则等待到时后发放;如果在1000ms内无法获取令牌,则直接返回false,无需等待。
        if (rateLimiter.tryAcquire(1000, TimeUnit.MILLISECONDS)) {
            //do sth
            return "成功获取令牌";
        } else {
            // do other
            return "获取失败";
        }
    }

    //阻塞机制
    @RequestMapping("/block")
    public String reateLimiterBlock(){
        //获取一个令牌,该方法会被阻塞知道获取令牌
        double waitTime = rateLimiter.acquire();
        //do sth
        return "等待"+waitTime+"秒后,成功获取令牌";
    }
}

建议使用非阻塞方式。

方法摘要

修饰符和类型 方法 描述
double acquire() 从RateLimiter获取一个许可,该方法会被阻塞直到获取到请求
double acquire(int permits) 从RateLimiter获取指定许可数,该方法会被阻塞直到获取到请求
static RateLimiter create(double permitsPerSecond) 根据指定的稳定吞吐率创建RateLimiter,这里的吞吐率是指每秒多少许可数(通常是指QPS,每秒多少查询)
static RateLimiter create(double permitsPerSecond, long warmupPeriod, TimeUnit unit) 根据指定的稳定吞吐率和预热期来创建RateLimiter,这里的吞吐率是指每秒多少许可数(通常是指QPS,每秒多少个请求量),在这段预热时间内,RateLimiter每秒分配的许可数会平稳地增长直到预热期结束时达到其最大速率。(只要存在足够请求数来使其饱和)
double getRate() 返回RateLimiter 配置中的稳定速率,该速率单位是每秒多少许可数
void setRate(double permitsPerSecond) 更新RateLimite的稳定速率,参数permitsPerSecond 由构造RateLimiter的工厂方法提供。
boolean tryAcquire() 从RateLimiter获取许可,如果该许可可以在无延迟下的情况下立即获取得到的话
boolean tryAcquire(int permits) 从RateLimiter获取许可数,如果该许可数可以在无延迟下的情况下立即获取得到的话
boolean tryAcquire(int permits, long timeout, TimeUnit unit) 从RateLimiter 获取指定许可数如果该许可数可以在不超过timeout的时间内获取得到的话,或者如果无法在timeout 过期之前获取得到许可数的话,那么立即返回false (无需等待)
boolean tryAcquire(long timeout, TimeUnit unit) 从RateLimiter 获取许可如果该许可可以在不超过timeout的时间内获取得到的话,或者如果无法在timeout 过期之前获取得到许可的话,那么立即返回false(无需等待)

参考资料:http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/util/concurrent/RateLimiter.html

相关文章

  • 基于信号量和令牌桶算法的限流

    限流的三种算法 限流主要有三种算法:信号量、漏桶算法和令牌桶算法。 信号量限制的是并发、资源。令牌桶限制的是QPS...

  • 基础架构 | 限流算法

    限流算法 令牌桶算法 漏桶算法

  • 一个轻量级的基于RateLimiter的分布式限流实现

    上篇文章(限流算法与Guava RateLimiter解析)对常用的限流算法及Google Guava基于令牌桶算...

  • Guava-RateLimiter详解

    常用的限流算法有漏桶算法和令牌桶算法,guava的RateLimiter使用的是令牌桶算法,也就是以固定的频率向桶...

  • 基于令牌桶算法的Java限流实现

    项目需要使用限流措施,查阅后主要使用令牌桶算法实现,为了更灵活的实现限流,就自己实现了一个简单的基于令牌桶算法的限...

  • Zuul 网关限流---Guava RateLimiter

    限流算法有漏桶算法和令牌桶算法,guava的RateLimiter使用的是令牌桶算法也就是以固定的频率向桶中放入令...

  • Nginx 限流配置(转)

    限流算法: 1. 令牌桶算法 算法思想是: 令牌以固定速率产生,并缓存到令牌桶中;令牌桶放满时,多余的令牌被丢弃;...

  • Nginx限流配置(转载)

    1、限流算法 令牌桶算法 算法思想是:a、令牌以固定速率产生,并缓存到令牌桶中;b、令牌桶放满时,多余的令牌被丢弃...

  • 漏桶算法与令牌桶算法的区别

    令牌桶算法是通过控制令牌生成的速度进行限流,漏桶算法是控制请求从桶中流出的速度进行限流。简单理解为:令牌桶控制进,...

  • (9)弹力设计篇之“限流设计”

    1、限流的策略 2、限流的算法:计数器、队列、漏斗和令牌桶。 3、如何基于响应时间来限流。 4、限流设计的要点 限...

网友评论

      本文标题:基于信号量和令牌桶算法的限流

      本文链接:https://www.haomeiwen.com/subject/kdtobftx.html