令牌token限流算法原理及代码

限流算法主要有如下几种:

  • 基于信号量Semaphore 只有数量维度,没有时间维度
  • 基于fixed window 带上了时间维度,不过在两个窗口的临界点容易出现超出限流的情况,比如限制每分钟10个请求,在00:59请求了10次,在01:01又请求了10次,而从00:30-01:30这个时间窗口来看,这一分钟请求了20次,没有控制好
  • 基于rolling window 就是要解决fixed window没解决的窗口临界问题,主要有基于token bucket的算法,以及基于leaky bucket的算法
  • token 钱包 bucket算法 token按指定速率添加到bucket中 一个bucket有其容量限制,超过其容量则多余的token会被丢弃 当请求到来时,先试图获取token,如果剩余token足够则放行,不够则不允许放行(可能等待token足够再继续)

2 简单实现

2.1 Java版

代码语言:javascript

AI代码解释

/** * The minimalistic token-bucket implementation */ public class MinimalisticTokenBucket { private final long capacity; private final double refillTokensPerOneMillis; private double availableTokens; private long lastRefillTimestamp; /** * Creates token-bucket with specified capacity and refill rate equals to refillTokens/refillPeriodMillis */ public MinimalisticTokenBucket(long capacity, long refillTokens, long refillPeriodMillis) { this.capacity = capacity; this.refillTokensPerOneMillis = (double) refillTokens / (double) refillPeriodMillis; this.availableTokens = capacity; this.lastRefillTimestamp = System.currentTimeMillis(); } synchronized public boolean tryConsume(int numberTokens) { refill(); if (availableTokens < numberTokens) { return false; } else { availableTokens -= numberTokens; return true; } } private void refill() { long currentTimeMillis = System.currentTimeMillis(); if (currentTimeMillis > lastRefillTimestamp) { long millisSinceLastRefill = currentTimeMillis - lastRefillTimestamp; double refill = millisSinceLastRefill * refillTokensPerOneMillis; this.availableTokens = Math.min(capacity, availableTokens + refill); this.lastRefillTimestamp = currentTimeMillis; } } private static final class Selftest { public static void main(String[] args) { // 100 tokens per 1 second MinimalisticTokenBucket limiter = new MinimalisticTokenBucket(100, 100, 1000); long startMillis = System.currentTimeMillis(); long consumed = 0; while (System.currentTimeMillis() - startMillis < 10000) { if (limiter.tryConsume(1)) { consumed++; } } System.out.println(consumed); } } }

以上是bucket4j给出的一个简单实现,用于理解token bucket算法。 这个算法没有采用线程去refill token,因为bucket太多的话,线程太多,耗cpu 这个算法没有存储每个period使用的token,设计了lastRefillTimestamp字段,用于计算需要填充的token 每次tryConsume的时候,方法内部首先调用refill,根据设定的速度以及时间差计算这个时间段需要补充的token,更新availableTokens以及lastRefillTimestamp 之后限流判断,就是判断availableTokens与请求的numberTokens

高性能限流器Guava RateLimiter

令牌桶算法,其核心是想通过限流器,必须拿到令牌。 只要我们能够限制发放令牌的速率,那么就能控制流速:

  • 令牌以固定速率添加到令牌桶中,假设限流速率是 r/秒,则令牌每 1/r 秒会添加一个
  • 假设令牌桶的容量是 b ,如果令牌桶已满,则新的令牌会被丢弃
  • 请求能够通过限流器的前提是令牌桶中有令牌

b 其实是burst的简写,意义是限流器允许的最大突发流量。比如b=10,而且令牌桶中的令牌已满,此时限流器允许10个请求同时通过限流器,这只是突发流量,这10个请求会带走10个令牌,所以后续流量只能按照速率 r 通过限流器。

如何实现呢?基于生产者-消费者模式?

  • 一个生产者线程定时向阻塞队列添加令牌
  • 试图通过限流器的线程则作为消费者线程
  • 只有从阻塞队列中获取到令牌,才允许通过限流器

设计看上去很完美,实现也简单,若并发量不大,这没有什么问题。可使用限流大部分都是高并发场景,而且系统压力已经临近极限了,此时这个实现就有问题了。 问题出在定时器,高并发下,系统压力已临近极限,定时器精度误差会很大,定时器本身还会创建调度线程,对系统性能影响极大。

所以Guava没有使用定时器,它是如何实现的呢?

Guava的令牌桶算法

关键是记录并动态计算下一令牌的发放时间。 假设令牌桶的容量为 b=1,限流速率 r = 1个请求/s。如下所示,若当前令牌桶无令牌,下一个令牌的发放时间是在第3s,而在第2s时,有个线程T1请求令牌,此时该如何处理?

  • 线程T1请求令牌

对于该请求令牌的线程,很显然需要等待1s,1s以后(第3s)它就能拿到令牌。下一个令牌发放的时间也要增加1秒,因为第3s发放的令牌已被线程T1预占。

  • 线程T1请求结束

假设T1在预占第3s令牌后,马上又有一个线程T2请求令牌

  • 线程T2请求令牌

由于下一个令牌产生的时间是第4s,所以线程T2要等待2s,才能获取到令牌,同时由于T2预占第4s令牌,所以下一令牌产生时间还要增加1s

  • 线程T2请求结束

线程T1、T2都是在下一令牌产生时间之前请求令牌,若线程在下一令牌产生时间之后请求令牌会咋样? 假设在线程T1请求令牌之后的5秒,即第7秒,线程T3请求令牌,如下图所示。

  • 线程T3请求令牌

由于第5s已产生一个令牌,所以此时线程T3可直接拿到令牌,无需等待。 在第7s,实际上限流器能产生3个令牌,第5、6、7秒各产生一个令牌。由于我们假设令牌桶的容量是1,所以第6、7秒产生的令牌就丢弃了,其实等价地你也可以认为是保留的第7秒的令牌,丢弃的第5、6秒的令牌,也就是说第7秒的令牌被线程T3占有了,于是下一令牌的的产生时间应该是第8秒

  • 线程T3请求结束

所以我们只需要记录一个下一令牌产生的时间,并动态更新它。

依然假设令牌桶的容量是1。关键是reserve()方法,这个方法会为请求令牌的线程预分配令牌,同时返回该线程能够获取令牌的时间。其实现逻辑就是上面提到的:如果线程请求令牌的时间在下一令牌产生时间之后,那么该线程立刻就能够获取令牌;反之,如果请求时间在下一令牌产生时间之前,那么该线程是在下一令牌产生的时间获取令牌。由于此时下一令牌已经被该线程预占,所以下一令牌产生的时间需要加上1秒。

3 小结

token bucket算法,是基于QPS来限流,其简单的实现,就是计算单位时间补充token的速率,然后每次tryConsume的时候根据速率修正availableTokens。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1139104.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ESM-2蛋白质语言模型完全指南:从入门到精通的实战宝典

ESM-2蛋白质语言模型完全指南&#xff1a;从入门到精通的实战宝典 【免费下载链接】esm2_t33_650M_UR50D 项目地址: https://ai.gitcode.com/hf_mirrors/facebook/esm2_t33_650M_UR50D ESM-2蛋白质语言模型是Meta AI推出的革命性生物信息学工具&#xff0c;能够像人类理…

Zonos语音合成技术深度洞察:从架构革新到行业应用重构

Zonos语音合成技术深度洞察&#xff1a;从架构革新到行业应用重构 【免费下载链接】Zonos Zonos-v0.1 is a leading open-weight text-to-speech model trained on more than 200k hours of varied multilingual speech, delivering expressiveness and quality on par with—o…

在MATLAB环境下,融合遗产算法(GA)和粒子群算法(PSO)的混合算法(GA_PSO)demo

在MATLAB环境下&#xff0c;融合遗产算法&#xff08;GA&#xff09;和粒子群算法&#xff08;PSO&#xff09;的混合算法&#xff08;GA_PSO&#xff09;demo&#xff0c;求解一定约束条件下的多元函数的极值。 将遗传算法的交叉变异操作融合进粒子群算法中&#xff0c;可以增…

Qwen3-VL-WEBUI移动端适配:轻量化推理性能优化案例

Qwen3-VL-WEBUI移动端适配&#xff1a;轻量化推理性能优化案例 1. 引言 随着多模态大模型在实际业务场景中的广泛应用&#xff0c;移动端适配与轻量化推理已成为落地过程中的关键挑战。Qwen3-VL-WEBUI 作为阿里开源的视觉-语言交互平台&#xff0c;内置了强大的 Qwen3-VL-4B-…

Qwen2.5-7B模型微调:云端GPU免环境配置教程

Qwen2.5-7B模型微调&#xff1a;云端GPU免环境配置教程 引言 作为一名算法工程师&#xff0c;你是否遇到过这样的困境&#xff1a;想要微调Qwen2.5-7B模型来适配业务需求&#xff0c;却在本地Docker环境配置中频频报错&#xff1f;公司IT支持响应缓慢&#xff0c;项目进度被一…

idv-login:告别繁琐扫码,一键畅玩第五人格

idv-login&#xff1a;告别繁琐扫码&#xff0c;一键畅玩第五人格 【免费下载链接】idv-login idv-login is an IdentityV login tool. 项目地址: https://gitcode.com/gh_mirrors/idv/idv-login 还在为每次登录《第五人格》都要掏出手机扫码而烦恼吗&#xff1f;&#…

快速验证创意:用AI 10分钟做出动态词云原型

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 生成一个社交媒体热点分析的可交互原型&#xff1a;1.模拟实时获取微博热搜关键词 2.ECharts-wordcloud动态更新效果 3.点击关键词关联显示相关话题趋势图 4.简约的深色主题UI 5.包…

颠覆性实时面部交换:DeepFaceLive零基础实战指南

颠覆性实时面部交换&#xff1a;DeepFaceLive零基础实战指南 【免费下载链接】DeepFaceLive Real-time face swap for PC streaming or video calls 项目地址: https://gitcode.com/GitHub_Trending/de/DeepFaceLive 你是否曾梦想在视频会议中瞬间变身好莱坞明星&#x…

没显卡怎么跑Qwen2.5-7B?云端GPU 1小时1块,小白5分钟上手

没显卡怎么跑Qwen2.5-7B&#xff1f;云端GPU 1小时1块&#xff0c;小白5分钟上手 作为一名前端开发者&#xff0c;周末看到Qwen2.5-7B发布的消息时&#xff0c;你一定跃跃欲试想用它来提升代码补全效率。但打开教程发现需要16G显存的N卡&#xff0c;而手头只有一台MacBook&…

zlib压缩库实战指南:从入门到精通的数据压缩解决方案

zlib压缩库实战指南&#xff1a;从入门到精通的数据压缩解决方案 【免费下载链接】zlib A massively spiffy yet delicately unobtrusive compression library. 项目地址: https://gitcode.com/gh_mirrors/zl/zlib zlib压缩库作为业界顶尖的高性能数据压缩解决方案&…

用AI写指针代码比传统开发快多少?实测对比

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 创建一个性能对比测试项目&#xff0c;要求&#xff1a;1. 设计5个不同复杂度的指针编程任务(从基础到高级) 2. 分别记录AI生成和人工编写的时间 3. 比较代码质量(错误率、可读性等…

猪齿鱼平台技术深度解析:企业级DevOps全生命周期管理实践指南

猪齿鱼平台技术深度解析&#xff1a;企业级DevOps全生命周期管理实践指南 【免费下载链接】choerodon 项目地址: https://gitcode.com/gh_mirrors/ch/choerodon 猪齿鱼(Choerodon)作为开源的企业级数字化平台&#xff0c;通过微服务架构和全流程自动化&#xff0c;为企…

终极LLM越狱指南:5分钟掌握AI安全测试核心技能

终极LLM越狱指南&#xff1a;5分钟掌握AI安全测试核心技能 【免费下载链接】Awesome-Jailbreak-on-LLMs Awesome-Jailbreak-on-LLMs is a collection of state-of-the-art, novel, exciting jailbreak methods on LLMs. It contains papers, codes, datasets, evaluations, and…

效率对比:RAGFLOW本地部署vs传统开发节省80%时间

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 创建一个效率对比演示项目&#xff1a;1.传统方式实现文档检索系统&#xff08;PythonElasticsearch&#xff09;2.RAGFLOW实现相同功能 3.并排对比界面 4.包含性能指标看板 5.自动…

SVG零基础入门:用在线工具轻松学矢量图形

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 设计一个交互式SVG学习工具&#xff0c;包含&#xff1a;1&#xff09;基础图形生成器&#xff08;通过拖拽参数学习各属性作用&#xff09;2&#xff09;SVG结构可视化解析&#…

对比传统方法:AI解决RDDI-DAP错误效率提升300%

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 创建一个RDDI-DAP错误解决效率对比工具&#xff0c;功能包括&#xff1a;1. 模拟10种常见RDDI-DAP错误场景&#xff1b;2. 记录传统手动解决所需时间和步骤&#xff1b;3. 展示AI辅…

Draco 3D压缩技术:终极解决方案让3D图形加载速度提升300%

Draco 3D压缩技术&#xff1a;终极解决方案让3D图形加载速度提升300% 【免费下载链接】draco Draco is a library for compressing and decompressing 3D geometric meshes and point clouds. It is intended to improve the storage and transmission of 3D graphics. 项目地…

SpringBoot3与Vue3全栈开发:5步快速搭建现代化项目

SpringBoot3与Vue3全栈开发&#xff1a;5步快速搭建现代化项目 【免费下载链接】SpringBoot3-Vue3-Demo 由我本人独立研发的一个基于 Spring Boot 3 和 Vue 3 的全栈示例项目&#xff0c;后端使用 MyBatis、MySQL 和本地缓存构建了高效的数据访问层&#xff0c;前端采用 Vue 3 …

零基础入门数据库同步:概念、工具与简单配置

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 开发一个面向新手的数据库同步工具&#xff0c;提供简洁直观的向导式界面。支持主流数据库的简单配置&#xff0c;自动生成同步脚本。包含详细的帮助文档和示例&#xff0c;让用户…

从零搭建菠萝农场官网:AI开发实战案例

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 创建一个专业级的菠萝农场官方网站&#xff0c;需要包含以下页面和功能&#xff1a;1.首页展示农场全景和特色 2.菠萝品种介绍页面&#xff08;至少5种&#xff09;3.种植过程展示…