深入解析限流的三种算法:信号量、漏桶算法和令牌桶算法的实现与应用

当前限制的三种算法

深入解析限流的三种算法:信号量、漏桶算法和令牌桶算法的实现与应用

当前有三种主要的限制算法:信号量,泄漏的铲斗算法和令牌桶算法。

信号量限制并发和资源。令牌存储桶限制QPS。

信号

信号量是计数信号量。它通常用于限制获得某个资源的线程数,并且可以根据Java并发并发软件包实现。

通过ACCEARIE()方法获得许可,该方法将阻塞直到获得许可。

通过Release()方法发布权限。

基于Java的并发实施


@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);//处理完后,释放一个许可
        }
    }
}

泄漏桶算法

泄漏的水桶算法有一个简单的想法。水(要求)首先进入漏水的水桶。泄漏的水桶以一定速度出现(接口具有响应率)。当水流过高时,它将直接溢出(访问频率超过接口响应。)然后拒绝请求,可以看出,泄漏的存储桶算法可以强行限制数据传输速率。示意图如下:

泄漏桶算法

令牌桶算法

令牌桶算法(令牌桶)和漏水桶具有相同的效果,但方向相反,易于理解。随着时间的流逝,系统将以常数的1/QPS时间间隔(如果QPS = 100,间隔为10ms)添加令牌添加令牌(假设它与漏洞相反,则有一个水龙头不断添加水)。如果存储桶已满,则不会添加它。当新请求到来时,每个请求都会带走一个令牌。如果没有令牌,它将阻止或拒绝服务

令牌桶算法

令牌桶算法比泄漏的水桶算法更优雅,并且适用于诸如Flash Sale之类的场景。此示例主要描述了基于Google的Guava代币算法的实现。

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

        
            com.google.guava
            guava
            25.0-jre
        

当前限制实现

@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+"秒后,成功获取令牌";
    }
}

建议使用非阻滞方法。

方法摘要

修饰符和类型方法描述

双倍的

获得()

获得Ratelimiter的许可,该方法将被阻止,直到检索请求

双倍的

获取(INT许可)

从Ratelimiter获取指定的权限号,该方法将被阻止,直到检索请求

静态比率

创建(双重允许)

基于指定的稳定吞吐率创建比例比率,其中吞吐量率是指每秒许可证数量(通常,QPS,每秒多少查询)

静态比率

创建(双允许允许长时间的harmuperpiood,时间单位单元)

根据指定的稳定吞吐量和热身时期创建比率的比率。在这里,吞吐量是指每秒许可证数量(通常是QP,每秒多少个请求)。在此热身时间,每秒比率的比率分配的许可证数量将顺利增长,直到在热身期结束时达到其最大速度为止。 (只要有足够的请求使其饱和)

双倍的

getrate()

返回稳定的比率配置,每秒的许可证数量

空白

setrate(双允许秒)

更新稳定的ratelimite速率,参数允许允许通过构造ratelimite的工厂方法提供。

布尔

TryAcquire()

如果立即获得许可证,请立即获得许可证

布尔

TryAcquire(INT许可)

如果可以立即获取许可证号,请立即获得许可证号

布尔

tryAcquire(int许可,长时间,时机单元)

如果可以在超时时间内获得许可证,或者如果超时,或者在超时到期之前无法获得许可证,请从Ratelimiter获取指定的许可证

布尔

tryAcquire(长时间,时间单元)

如果可以在不超时的超时期内获得许可证,或者如果超时到期之前获得许可证,请从Ratelimiter获得许可证

参考:

你可能想看:
« 上一篇
下一篇 »

相关推荐

java中什么是冒泡,冒泡算法

2026年09月06日

27阅读

java中冒号,java双冒号

2026年09月06日

26阅读

java中的->,java中的是什么意思

2026年09月06日

24阅读

java中的super用法,Java中super的说明

2026年09月06日

28阅读

java中反射的应用,java中反射的应用场景

2026年09月06日

26阅读

java中开关的定义,Java关键字有哪些

2026年09月06日

26阅读