RateLimiter 的底层实现是啥?

2023-11-17

点击上方“Java基基”,选择“设为星标”

做积极的人,而不是积极废人!

源码精品专栏

 

来源:my.oschina.net/floor/blog/4965200


前言

本文不是一个RateLimiter的详细分析,仅仅是概要分析。

令牌桶算法

一说到RateLimiter,必然要是说的令牌桶,它的大致逻辑如下

按图实现

令牌桶的图,网上到处可见,按图实现也非常简单,无非是定时添加令牌桶,并提供一个获取令牌的函数,博主实现了一遍代码如下:

import java.util.concurrent.*;

public class MyRateLimiter {
    //令牌桶
    BlockingQueue<Integer>TOKEN_BUCKET=new LinkedBlockingDeque<>(5);

    public static void main(String[] args) {
        MyRateLimiter myRateLimiter=new MyRateLimiter();
        myRateLimiter.addTokenFixedRate();
       for(int i=0;i<10;i++){
                myRateLimiter.acqurie();
                System.out.println("第几次执行i:" + i + ",执行时间为:" + System.currentTimeMillis());
        }
    }
   /**
    * 定时添加令牌
    */
    public void addTokenFixedRate(){
        ScheduledExecutorService scheduledExecutorService= Executors.newSingleThreadScheduledExecutor();
        scheduledExecutorService.scheduleAtFixedRate(()->{
                    boolean suc=TOKEN_BUCKET.offer(1);
                    if(!suc){
                        System.out.println("令牌桶满了丢弃");
                    }
        },0,200,TimeUnit.MILLISECONDS);
    }

    public void acqurie(){
        while (TOKEN_BUCKET.poll()==null){};
    }

}

测试结果如下,基本满足要求

RateLimiter概要实现

我一开始是按照自己实现的逻辑,去查看Guava的RateLimiter的源码的,结果发现****RateLimiter根本没有集合充当桶,核心是记录了下一令牌产生的时间与现存令牌数,并动态更新它们。** **

概要逻辑图如下:

按照这个图看核心代码就比较容易了,摘录核心代码如下:

@CanIgnoreReturnValue
public double acquire(int permits) {
  long microsToWait = reserve(permits);
  stopwatch.sleepMicrosUninterruptibly(microsToWait);
  return 1.0 * microsToWait / SECONDS.toMicros(1L);
}
//Reserve 一路向下能查到如下代码  reserveEarliestAvailable

final long reserveEarliestAvailable(int requiredPermits, long nowMicros) {
    resync(nowMicros);
    long returnValue = nextFreeTicketMicros;
 // 现存令牌可以提供的令牌数
    double storedPermitsToSpend = min(requiredPermits, this.storedPermits);
 //需要刷新的令牌数
    double freshPermits = requiredPermits - storedPermitsToSpend;
 //等待时间=需要刷新的令牌数*固定间隔+存储许可等待时间
    long waitMicros =
        storedPermitsToWaitTime(this.storedPermits, storedPermitsToSpend)
            + (long) (freshPermits * stableIntervalMicros);
 //下次令牌生产时间=本次令牌生产时间+等待时间
    this.nextFreeTicketMicros = LongMath.saturatedAdd(nextFreeTicketMicros, waitMicros);
    this.storedPermits -= storedPermitsToSpend;
    return returnValue;
  }

总结

RateLimiter根本没有集合充当桶,核心是记录了下一令牌产生的时间与现存令牌数,并动态更新它们

不足

SmoothWarmingUp 与SmoothBursty 并没有详细看。

- END -

欢迎加入我的知识星球,一起探讨架构,交流源码。加入方式,长按下方二维码噢

已在知识星球更新源码解析如下:

最近更新《芋道 SpringBoot 2.X 入门》系列,已经 20 余篇,覆盖了 MyBatis、Redis、MongoDB、ES、分库分表、读写分离、SpringMVC、Webflux、权限、WebSocket、Dubbo、RabbitMQ、RocketMQ、Kafka、性能测试等等内容。

提供近 3W 行代码的 SpringBoot 示例,以及超 4W 行代码的电商微服务项目。

获取方式:点“在看”,关注公众号并回复 666 领取,更多内容陆续奉上。

文章有帮助的话,在看,转发吧。
谢谢支持哟 (*^__^*)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

RateLimiter 的底层实现是啥? 的相关文章

随机推荐

  • 如何保证测试用例覆盖全面

    测试用例覆盖度一般是从以下几方面衡量的 1 测试需求的覆盖 保证所有需求都已经设计用例 2 测试特性的覆盖 保证所有不同类型已覆盖 如 功能测试 性能测试等 3 平台与层次的覆盖 保证所有平台有用例覆盖 不同层次都有设计用例 如业务层 接口
  • JavaScript随机生成颜色功能

    思路 实现一个函数 随机生成颜色 格式为 000000 颜色由a f A F 0 9 3种字母任意组成 且 后面是3位或者6位 只要随机生成一个数字是奇数或者偶数来随机出是3位或者6位 然后在随机其下标循环上面步骤确认的次数 functio
  • 设计模式之简单工厂模式(Simply Factory)摘录

    从设计模式的类型上来说 简单工厂模式是属于创建型模式 又叫静态工厂方法 Static Factory Method 模式 但不属于23种GOF设计模式之一 简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例 简单工厂模式是工厂模式家族
  • 数据库索引

    3 1 概括 索引 Index 是数据库中的一种存储结构 用于快速查找数据 索引通常是在数据库表上创建的 可以用于加速查询 排序和数据的唯一性验证 索引可以理解为图书中的目录 通过目录我们可以很快找到页码对应的内容 当表中有大量数据需要查询
  • 计算机竞赛 基于计算机视觉的身份证识别系统

    0 前言 优质竞赛项目系列 今天要分享的是 基于机器视觉的身份证识别系统 该项目较为新颖 适合作为竞赛课题方向 学长非常推荐 更多资料 项目分享 https gitee com dancheng senior postgraduate 1
  • 封裝:WPF基于Vlc.DotNet.Wpf封装的视频播放器

    一 目的 应用自带的MediaElement播放器播放文件类型有限 有些格式还需要安装插件 由此应用第三方工具包Vlc DotNet Wpf封装支持多格式的视频播放器 二 环境 VS2019 Win10 Vlc DotNet Wpf HeB
  • 校友全剧透CMU :ME + 转CS + 其他主要项

    在CMU待了一个半学期了 对于留学 对于CMU 对于ME 对于转CS 对于CMU其它各种项目都了解的更多了一些 也有不同的体会 我想这篇文章应该会对任何一个申请了CMU 或者想申请CMU 甚至每一个想要出国留学的人都会有一点帮助 写下面这些
  • Easy-Es核心功能深度介绍

    背景 近期随着项目开源后热度的不断上涨 越来越多小伙伴开始对框架核心功能感兴趣 今天就让我带大家深入源码和架构 一起探索Easy Es 简称EE 的核心功能是如何被设计和实现的 和众多ORM框架一样 EE最为核心的功能就是CRUD 增删改查
  • selenium3之selenium-server-standalone-3.8.1.jar启动

    查看安装的selenium版本 下载对应版本的selenium server 下载地址 http selenium release storage googleapis com index html 需要先安装JDK 自行百度安装 启动se
  • Linux的NFS共享目录操作步骤

    首先准备两台Linux 一台服务器 一台客户机 IP地址可自行设置 两台防火墙都要关闭 配置服务器IP地址 172 20 10 11 配置客户机IP地址 172 20 10 12 先关闭防火墙 systemctl stop filewall
  • 【JavaScript】页面加载 解决Uncaught TypeError: Cannot set property of undefined at

    在初学js的时候 有同学会遇到 Uncaught TypeError Cannot set property onmouseover of undefined at html 的问题 这个问题牵扯到页面加载顺序的问题 我们知道 页面的加载顺
  • 使用Prometheus+Grafana+Spring Boot Actuator监控应用

    在企业级的应用中 监控往往至关重要 监控可以帮助我们预防故障 预测变化趋势 在达到阈值的时候报警 为排查生产问题提供更多的信息 如果我们不知道我们程序的运行情况 当线上系统出现了事故再去排查就需要花费更多的时间 如果能提前监控 就能早做准备
  • VScode的PHP远程调试模式Xdebug

    目录 第一步 安装VScode中相应插件 remote ssh的原理 ssh插件 PHP相关插件 第二步 安装对应PHP版本的xdebug 查看PHP具体配置信息的phpinfo页面 1 首先 打开php编辑器 新建一个php文件 例如 i
  • CentOS7下rsync实现服务器之间实时同步

    rsync简介 rsync是类unix系统下的数据镜像备份工具 使用快速增量备份工具Remote Sync可以远程同步 支持本地复制 或者与其他SSH rsync主机同步 文章主讲实际操作 不再进行详细叙述 想要了解更多可以查看百度百科 一
  • QT 编译报错“QWidget: Must construct a QApplication before a QWidget”

    一 错误原因 1 在构造QApplication之前创建了部件 某个类或者其子类中采用了静态的qWidget或者其子类 由于静态或者全局对象在 main 之前就产生了 所以 早于main 里的QApplication对象 2 混用 debu
  • Python实现敏感词过滤

    在我们生活中的一些场合经常会有一些不该出现的敏感词 我们通常会使用 去屏蔽它 例如 尼玛 gt 一些骂人的敏感词和一些政治敏感词都不应该出现在一些公共场合中 这个时候我们就需要一定的手段去屏蔽这些敏感词 下面我来介绍一些简单版本的敏感词屏蔽
  • 【面试真题】今日头条大数据面试100题,收藏备用

    1 简述WordCount 的实现过程 2 简述MapReduce与 Spark 的区别与联系 3 Spark 在客户端与集群运行的区别 4 相同的 SQL 在 HiveSql 与 SparkSQL 的实现中 为什么 Spark 比 Had
  • Android MVC、MVP、MVVM、MVI架构对比及示例

    随着Android应用开发技术的不断成熟 应用功能越来越丰富 迭代速度要求的越来越高 应用的开发架构也在不断演进 优化 从MVC MVP到MVVM 到如今的MVI 谷歌官方也在不断推广 优化适合Android平台的开发架构 并推出了一系列的
  • centos7部署openwhisk

    实验环境 Openwhisk 192 168 1 36 make lean部署 Fn project 192 168 1 35 Openwhisk核心提炼 环境准备 nodejs12 curl sL https rpm nodesource
  • RateLimiter 的底层实现是啥?

    点击上方 Java基基 选择 设为星标 做积极的人 而不是积极废人 源码精品专栏 原创 Java 2020 超神之路 很肝 中文详细注释的开源项目 RPC 框架 Dubbo 源码解析 网络应用框架 Netty 源码解析 消息中间件 Rock