Guava-RateLimiter令牌桶限流算法

Guava RateLimiter实战:从令牌桶算法到高并发限流策略 本文深入探讨了Guava RateLimiter在高并发场景下的限流策略,详细解析了令牌桶算法的原理与实现。通过实战案例展示了如何配置和使用RateLimiter,包括基础限流、突发流量处理、动态调参等技巧,帮助开发者有效应对高并发挑战,提升系统稳定性。 阅读详情

前言

高并发系统一般会才采用三种策略来保护系统:缓存、服务降级、限流;

  1. 缓存:比如Redis。先查询缓存,如果命中则返回;如果没有数据,查询数据库后返回并写入缓存;
  2. 服务降级:比如Spring Cloud Hystrix。当服务出现问题需要暂时屏蔽掉,并在上游及时响应用户请求;
  3. 限流:通过对并发访问/请求进行限速,或者对一个时间窗口内的请求进行限速来保护系统,一旦达到限制速率则可以拒绝服务、排队或等待、降级等处理;

1. 限流算法简介

常见有漏桶算法和令牌桶算法;

  1. 漏桶算法
    漏桶作为计量工具(The Leaky Bucket Algorithm as a Meter)时,可以用于流量整形(Traffic Shaping)和流量控制(TrafficPolicing),漏桶算法的描述如下:
    一个固定容量的漏桶,按照常量固定速率流出水滴;
    如果桶是空的,则不需流出水滴;
    可以以任意速率流入水滴到漏桶;
    如果流入水滴超出了桶的容量,则流入的水滴溢出了(被丢弃),而漏桶容量是不变的。
    漏桶(Leaky Bucket)算法思路很简单,水(请求)先进入到漏桶里,漏桶以一定的速度出水(接口有响应速率),当水流入速度过大会直接溢出(访问频率超过接口响应速率),然后就拒绝请求,可以看出漏桶算法能强行限制数据的传输速率.示意图如下:
    在这里插入图片描述
    可见这里有两个变量,一个是桶的大小,支持流量突发增多时可以存多少的水(burst),另一个是水桶漏洞的大小(rate)。
    因为漏桶的漏出速率是固定的参数,所以,即使网络中不存在资源冲突(没有发生拥塞),漏桶算法也不能使流突发(burst)到端口速率.因此,漏桶算法对于存在突发特性的流量来说缺乏效率.

  2. 令牌桶算法
    令牌桶算法是一个存放固定容量令牌的桶,按照固定速率往桶里添加令牌。令牌桶算法的描述如下:
    假设限制2r/s,则按照500毫秒的固定速率往桶中添加令牌;
    桶中最多存放b个令牌,当桶满时,新添加的令牌被丢弃或拒绝;
    当一个n个字节大小的数据包到达,将从桶中删除n个令牌,接着数据包被发送到网络上;
    如果桶中的令牌不足n个,则不会删除令牌,且该数据包将被限流(要么丢弃,要么缓冲区等待)。
    令牌桶算法(Token Bucket)和 Leaky Bucket 效果一样但方向相反的算法,更加容易理解.随着时间流逝,系统会按恒定1/QPS时间间隔(如果QPS=100,则间隔是10ms)往桶里加入Token(想象和漏洞漏水相反,有个水龙头在不断的加水),如果桶已经满了就不再加了.新请求来临时,会各自拿走一个Token,如果没有Token可拿了就阻塞或者拒绝服务。
    在这里插入图片描述
    令牌桶的另外一个好处是可以方便的改变速度. 一旦需要提高速率,则按需提高放入桶中的令牌的速率. 一般会定时(比如100毫秒)往桶中增加一定数量的令牌, 有些变种算法则实时的计算应该增加的令牌的数量.

这两种算法的主要区别在于“ 漏桶算法”能够强行限制数据的传输速率,而“令牌桶算法”在能够限制数据的平均传输速率外,还允许某种程度的突发传输。在“令牌桶算法”中,只要令牌桶中存在令牌,那么就允许突发地传输数据直到达到用户配置的门限,因此它适合于具有突发特性的流量。

2. RateLimiter

Guava中开源出来一个令牌桶算法的工具类RateLimiter,可以轻松实现限流的工作。

RateLimiter有两个实现类:SmoothBursty和SmoothWarmingUp;
两者都是令牌桶算法的变种实现,区别在于SmoothBursty加令牌的速度是恒定的,而SmoothWarmingUp会有个预热期,在预热期内加令牌的速度是慢慢增加的,直到达到固定速度为止。其适用场景是,对于有的系统而言刚启动时能承受的QPS较小,需要预热一段时间后才能达到最佳状态。
使用RateLimiter的时候,查看源码可知,具体实现根据create方法参数,返回不同的实现类;

2.1 方法摘要

返回类型方法描述
doubleacquire();
从RateLimiter获取一个令牌,该方法会被阻塞直到获取到请求
doubleacquire(int permits);
从RateLimiter获取指定令牌数,该方法会被阻塞直到获取到请求
static RateLimitercreate(double permitsPerSecond);
根据指定的稳定吞吐率创建RateLimiter,这里的吞吐率是指每秒多少令牌数(通常是指QPS,每秒多少查询)
static RateLimitercreate(double permitsPerSecond, long warmupPeriod, TimeUnit unit);
根据指定的稳定吞吐率和预热期来创建RateLimiter,这里的吞吐率是指每秒多少令牌数(通常是指QPS,每秒多少个请求量),在这段预热时间内,RateLimiter每秒分配的许可数会平稳地增长直到预热期结束时达到其最大速率。(只要存在足够请求数来使其饱和)
booleantryAcquire();
从RateLimiter 获取令牌,permits默认为1
booleantryAcquire(int permits);
从RateLimiter获取指定令牌数
booleantryAcquire(int permits, long timeout, TimeUnit unit);
从RateLimiter 获取指定令牌数,如果在指定超时间获取到的话返回true,否则返回false
booleantryAcquire(long timeout, TimeUnit unit);
从RateLimiter 获取令牌,permits默认为1,如果在指定超时间获取到的话返回true,否则返回false

2.2 RateLimiter使用示例

示例1说明:创建一个令牌桶,每秒生成一个令牌,申请失败立即返回。使用CountdownLatch计数器模拟多线程并发:调用await()方法阻塞当前线程,当计数完成后,唤醒所有线程并发执行。

public static void main(String[] args) {
        //每秒生成一个令牌,返回SmoothBursty实现类
        RateLimiter rateLimiter = RateLimiter.create(1D);
        CountDownLatch countDownLatch = new CountDownLatch(1);
        ExecutorService executor = Executors.newCachedThreadPool();
        for (int i = 0; i < 10; i++) {
            Runnable runnable = () -> {
                try {
                    countDownLatch.await();
                    //尝试获取令牌桶中一个令牌,失败立即返回
                    if (rateLimiter.tryAcquire()) {
                        System.out.println(Thread.currentThread().getName() + ": " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + "获取到令牌");
                    } else {
                        System.out.println(Thread.currentThread().getName() + ": byebye");
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            };
            executor.submit(runnable);
        }
        countDownLatch.countDown();
        executor.shutdown();
    }

在这里插入图片描述

示例2说明:创建一个令牌桶,每秒生成0.1个令牌,即每10s才会有一个令牌,超时时间设置成60s,60s内获取不到令牌返回失败,60s内可以生成6个令牌,加上创建时桶里会有一个令牌,所以超时前最终会有7条线程拿到令牌,并且每个令牌获取时间相隔10s。使用CountdownLatch计数器模拟多线程并发:调用await()方法阻塞当前线程,当计数完成后,唤醒所有线程并发执行。

public static void main(String[] args) {
        //每秒生成一个令牌,返回SmoothBursty实现类
        RateLimiter rateLimiter = RateLimiter.create(0.1D);
        CountDownLatch countDownLatch = new CountDownLatch(1);
        ExecutorService executor = Executors.newCachedThreadPool();
        for (int i = 0; i < 10; i++) {
            Runnable runnable = () -> {
                try {
                    countDownLatch.await();
                    //尝试获取令牌桶中一个令牌,最多等待60秒
                    if (rateLimiter.tryAcquire(60, TimeUnit.SECONDS)) {
                        System.out.println(Thread.currentThread().getName() + ": " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + "获取到令牌");
                    } else {
                        System.out.println(Thread.currentThread().getName() + ": byebye");
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            };
            executor.submit(runnable);
        }
        countDownLatch.countDown();
        executor.shutdown();
    }

在这里插入图片描述

SpringBoot集成Guava RateLimiter:实战令牌桶算法实现API限流 本文详细介绍了如何在SpringBoot应用中集成Guava RateLimiter实现API限流,通过令牌桶算法有效控制流量。文章涵盖基础手动限流、注解+AOP高级用法以及动态配置中心集成,并提供了生产环境中的避坑指南和真实秒杀系统案例,帮助开发者构建高可用服务。 阅读详情

相关推荐

guava限流器RateLimiter使用简介(Springboot实现)

令牌产生的稳定速率,只是这里的速率是转换成了两个令牌生产之间的时间间隔(毫秒)。之所以是稳定速率,是因为SmoothWarmUp,在预热阶段产生令牌的速率会低于这个值。RateLimiter初始化的时候,传入的permitsPerSecond表示的是每秒产生的产生的令牌个数,也就是说令牌的生产速率的时间单位就给固定了,那么stableIntervalMicros = 1s/permitsPerSecond。

justlpf的专栏 1万+

简单分析Guava中RateLimiter中的令牌桶算法的实现

为什么80%的码农都做不了架构师?>>> ...

weixin_33730836的博客 468

guava之限流RateLimiter

常用的限流方式和场景有: 限制总并发数(比如数据库连接池、线程池) 限制瞬时并发数(如nginx的limitconn模块,用来限制瞬时并发连接数,Java的Semaphore也可以实现) 限制时间窗口内的平均速率(如Guava的RateLimiter、nginx的limitreq模块,限制每秒的平均速率) 其他:比如如限制远程接口调用速率、限制MQ的消费速率。另外还可以根据网络连接数、网络流量、CPU或内存负载等来限流。 我们常说的限流,其实更多的都是指时间窗口内的平均速率,所以往往这种限流方式成了

sinat_14913533的博客 1万+

SpringBoot基于guava集成令牌桶算法

SpringBoot基于guava集成令牌桶算法

qq_38254635的博客 2389

RateLimiter源码阅读

俗话说得好,缓存,限流和降级是系统的三把利剑。刚好项目中每天早上导出数据时因调订单接口频率过高,订单系统担心会对用户侧的使用造成影响,让我们对调用限速一下,所以就正好用上了。     常用的限流算法有2种:漏桶算法和令牌桶算法。    漏桶算法    漏桶算法:请求先进入“桶”中,然后桶以一定的速率处理请求。如果请求的速率过快会导致桶溢出。根据描述可以知道,漏桶算法会强制限制请求处理的速度。任你请

一只海滩上的贝壳 5087

Guava——平滑限流

1.常用限流方法对于一个应用系统来说一定会有极限并发/请求数,即总有一个TPS/QPS阀值,如果超了阀值则系统就会不响应用户请求或响应的非常慢,因此我们最好进行过载保护,防止大量请求涌入击垮系统。常见的限流方法有:容器限流常见的web容器其实也具备限流的功能。以Tomcat容器为例,其Connector 其中一种配置有如下几个参数:acceptCount:如果Tomcat的线程都忙于响应,新来的连...

ShiXueTanLang的博客 4012

限流算法-令牌桶算法

常用的限流算法有令牌桶法和漏桶,而Google开源项目Guava中的RateLimiter使用的就是令牌桶算法。在使用令牌桶算法时需要引入如下依赖: <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>29.0-jre</version> </dependency&g

北辰 964

【编程实践】Guava RateLimiter 限流器实现原理 & 用形象的生活中的例子来讲解一下令牌桶算法(Token Bucket Algorithm)原理

gpt-4:Guava RateLimiter 是 Google 提供的一个用于限制系统吞吐量的工具类,它可以限制系统每秒处理的任务数量,从而保护系统的稳定性。RateLimiter 的实现原理主要基于令牌桶算法,其核心思想是系统以固定的速率向桶中添加令牌,处理请求时需要从桶中获取令牌,如果桶中没有令牌,则需要等待,直到桶中有令牌为止。具体实现过程如下:初始化时,设置令牌生成速率,即每秒生成的令牌数。当请求到来时,首先计算需要的令牌数,然后计算获取这些令牌需要等待的时间。

AI天才研究院 597

Guava中常用的4种经典限流算法介绍

限流算法

gb4215287的博客 1587

一桶令牌的时间账本:四类限流算法的边界推演与Guava RateLimiter源码精读

限流的难点不在背出算法名,而在算清每一笔账:按哪一秒计数、超额请求排队还是拒绝、空闲后能否突发、集群总量如何约束。本文在可复现的虚拟时间实验台上对比固定窗口、滑动窗口、漏桶与令牌桶,实测边界双倍突发与分桶滑动的真实上界,拆解Nginx limit_req的千分位记账与延迟机制,纠正Resilience4j常被误称漏桶的说法,并逐行精读Guava SmoothRateLimiter的预消费、懒惰补账与预热积分,复刻迷你限流器与其完成七万次零差异对账,最后给出集群配额、分层防护与参数确定的方法。

曾经“等你生日那天”都遥远得像未来,如今却可欢愉的挥手说“下个十年见” 86万+

项目限流、令牌桶算法、漏桶算法、Guava RateLimiter、Guava+自定义注解限流、Nginx限流、Redis + 注解实现限流、Sentinel 分布式限流、网关限流

项目限流、令牌桶算法、漏桶算法、Guava RateLimiter、Guava+自定义注解限流、Nginx限流、Redis + 注解实现限流、Sentinel 分布式限流、网关限流

殇的不悔 427

限流实战:guava的RateLimiter实现令牌桶算法限流

目录 1 引入依赖 2 限流实现 3自定义拦截器,在拦截器中实现限流 4 实现WebMvcConfigurer 添加自定义拦截器 5RateLimiterAnnotation 实现 6 controller 类实现 7 通过 jmeter 进行测试限流 限流和限流算法已经介绍了常见的限流算法。guava 的 RateLimiter 使用的是令牌桶算法。本次实战,...

javaTalk 2035

linux redis7 完整的集群搭建过程

一。安装: 1.1 说明: Redis官方只提供了源码,并没有提供经过编译之后的安装包。 因此,安装Redis,要先编译、后安装。(即源码安装方式) 注意:需要联网安装 1.2 安装编译的工具: yum install gcc gcc-c++ -y 1.3 下载tar包,上传到linux服务器,解压配置环境变量 1.4 cd +解压的目录下:编译 make 注意:如果编译失败,请重新进行解压编译,...

m0_38028438的博客 719

Guava提供的RateLimiter限流原理以及漏桶算法和令牌桶算法

文章目录漏桶算法、令牌桶算法思路及使用场景RateLimiter实现原理SmoothBurstySmoothWarmingUp 漏桶算法、令牌桶算法思路及使用场景 在介绍RateLimiter之前我们先看下常说的漏桶算法和令牌桶算法,看下两种算法的思想和适用场景: 漏桶算法: 结合上面的图,漏桶算法就是将请求放入桶中,然后始终以一个固定的速率从桶中取出请求来处理,当桶中等待的请求数超过上限后(桶的容量固定),后续的请求就不再加入桶中,而是执行拒绝策略(比如降级) 适用于需要以固定速率的场景,而在多数业务场

肆頭的博客 3722

保姆级教程:用CANoe的LIN Slave Conformance Tester搞定一致性测试(附LDF配置避坑点)

本文详细介绍了如何使用CANoe的LIN Slave Conformance Tester进行汽车电子LIN从节点一致性测试,包括测试环境搭建、LDF文件配置、多通道测试技巧及常见问题解决方案。通过实战案例和高级配置技巧,帮助工程师高效完成测试任务,确保LIN总线通信的可靠性。

weixin_30385925的博客 523

zynq7020的arm A9核降频实录

zynq arm9 cortex a9 降频

qq_40011737的博客 8763

Java服务端中的限流实现:使用Guava RateLimiter与令牌桶算法

其中,令牌桶算法在实践中更为常用,因为它允许突发流量,同时限制总流量。大家好,我是微赚淘客返利系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!令牌桶算法通过一个固定容量的桶来存储令牌,系统按照设定的速率向桶中添加令牌。当请求到来时,系统从桶中取出一个令牌,允许请求通过。通过这种方式,我们可以确保每秒钟最多只处理5个请求,多余的请求将被限流器拒绝。和令牌桶算法来实现限流的方式,并结合Java代码示例进行讲解。通过生成令牌来控制请求速率。,它基于令牌桶算法实现,可以在应用中非常方便地实现限流。

技术研究中心 1487

华为 MetaERP 通过元数据驱动的多组织架构 + 内部交易协同 + 自动对账引擎 + 合并规则引擎,实现多组织内部往来与合并报表的全流程自动抵消,核心是源头标准化、过程自动化、结果可追溯

摘要: 华为MetaERP通过元数据驱动的多组织架构与主数据标准化,实现内部往来与合并报表全流程自动化。其核心包括:统一组织模型与主数据(确保数据口径一致)、内部交易协同(自动生成对称凭证)、智能对账引擎(多维度自动匹配差异)、合并规则引擎(配置化抵消模板)。依托GaussDB高性能数据库与流批一体架构,华为全球88家子公司合并报表效率提升400%,关账时间缩短至2小时,支持多准则、多币种自动抵消,审计全程可追溯。相比传统ERP,MetaERP在协同性、自动化与扩展性上优势显著,为跨国集团提供高效、准确的合

金牌架构师 264

Guava RateLimiter单机限流实战:从令牌桶算法到Spring Boot集成

在分布式系统和高并发场景中,流量控制是保障服务稳定性的核心技术之一。其核心原理是通过算法限制单位时间内的请求数量,防止系统因过载而崩溃。令牌桶算法作为一种经典的限流模型,通过固定容量的桶和恒定速率添加令牌的机制,既能平滑处理突发流量,又能保证长期平均速率。这一技术价值在于以轻量级的方式实现服务自我保护,避免级联故障,提升系统韧性。在应用场景上,单机限流特别适用于应用内部资源保护、第三方API调用频率控制、日志输出速率限制等场景。本文以Google Guava库中的RateLimiter为核心,深入解析其平滑

weixin_30682415的博客 305

混响效果的编程实现:Schroeder混响模型与Moorer型混响

Schroeder混响模型是由Manfred R. Schroeder在1962年提出的,它基于一系列串联的反射器(Allpass Comb Filters)和并联的反射器(Feedback Comb Filters)构成。Schroeder混响模型是由Manfred R. Schroeder在1962年提出的,它基于一系列串联的反射器(Allpass Comb Filters)和并联的反射器(Feedback Comb Filters)构成。通过调整各个反射器和全通滤波器的参数,可以实现不同的混响效果。

2301_79326857的博客 1081

把 ABAP writable CDS view entity 讲透:从只读建模到可写模型的 ABAP CDS 新能力

摘要:SAP引入的writable CDS view entity突破了传统CDS视图只读的限制,允许通过ABAP SQL直接进行数据修改。该特性通过WRITABLE关键字定义,使CDS视图成为与数据库表同等级别的可写对象。其核心价值在于为数据集成、中间层同步等场景提供结构化写入入口,但需注意不应绕过业务规则。最佳实践建议保持底层表结构简单映射,避免复杂变形。这一特性标志着CDS从单纯消费模型向双向数据交互能力的演进,为ABAP开发提供了新的数据边界设计思路。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 1313

令牌桶算法和漏桶算法python_经典限流方法——漏桶、令牌桶与Guava RateLimiter的实现...

点击上方蓝色字体,选择“设为星标”回复”资源“获取更多资源大数据技术与架构点击右侧关注,大数据开发领域最强公众号!暴走大数据点击右侧关注,暴走大数据!高并发的业务系统经常要接受大流量的考验,为了保证系统的响应度和稳定性,往往都需要对有风险的接口实施限流(rate limiting),更高大上的说法则是“流量整形”(traffic shaping)。限流的思想最初来源于计算机网络,有两种经...

weixin_39887925的博客 323

SAP 生产订单归档简介

通常在使用了几年的SAP后,系统中会产生非常多的数据在系统中,特别是制造业的生产订单,常年的累积会存在很多的订单在系统中,这个时候就可以使用归档的功能,对生产订单进行处理。标记DLFL的前提是需要完成生产订单的差异结算,DLFL标记可以清除掉生产订单的相关需求和预留。6、在执行CO78选择删除,前面的操作相当于我们把需要归档的数据写入了数据库中,现在正式进行数据的归档删除。然后我们co03在去看生产订单,可以看到生产订单中多了删除的状态和标记的状态。我这里直接执行的程序PPARCHP1,效果其实是一样的。

我小时候很黑的博客 2284

常见限流算法 与 Guava RateLimiter实现

常见限流算法以及Guava RateLimiter源码分析

lc 3041

AI产品经理面试宝典第94天:RAG知识库构建与预处理策略面试指南

本文深入解析RAG知识库构建的核心挑战与预处理策略,涵盖文档格式转换、问答对生成及自动化测试全流程,为AI产品经理提供面试必备的实战方法论与避坑指南,助你精准应对技术深度类问题。

打造全国最全的AI Agent开发知识领域的博客 311

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

Guava RateLimiter单机限流实战:令牌桶算法原理与生产级应用

限流是保障系统稳定性的核心技术之一,其核心原理是通过算法控制请求流量,防止系统因过载而崩溃。在众多限流算法中,令牌桶算法因其允许合理突发流量的特性而被广泛应用。Guava RateLimiter作为Google提供的单机限流组件,基于令牌桶算法实现,提供了平滑突发和预热两种模式,能够有效保护服务实例免受流量洪峰冲击。在分布式架构中,单机限流是构建韧性系统的第一道防线,它与分布式限流形成互补,共同保障系统高可用。本文聚焦于Guava RateLimiter的实战应用,深入解析其令牌桶算法原理,并结合典型场景如

weixin_33507732的博客 256

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

上一篇: [转]分布式锁和队列同步器
下一篇: 使用自定义注解+AOP实现RateLimiter令牌桶限流
可爱徐叔叔
博客等级 码龄7年 5粉丝 12原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值