0

0

Python 令牌桶限流的异步版本

舞夢輝影

舞夢輝影

发布时间:2026-02-16 16:48:49

|

470人浏览过

|

来源于php中文网

原创

asyncio版令牌桶不能直接套用threading版逻辑,因为threading.lock在协程中会阻塞event loop且不可await,导致并发请求串行化、吞吐量骤降;必须改用asyncio.lock或无锁结构。

python 令牌桶限流的异步版本

asyncio 版令牌桶为什么不能直接套用 threading 版逻辑

因为 threading.Lock 在协程里会阻塞整个 event loop,不是 awaitable;用它会导致所有并发请求串行化,吞吐量断崖下跌。真正的异步限流必须用 asyncio.Lock 或无锁结构(如原子计数器 + asyncio.sleep)。

  • 常见错误现象:RuntimeWarning: coroutine 'Lock.acquire' was never awaited,或压测时 QPS 卡在 1–2,远低于预期
  • 正确做法:用 asyncio.Lock 包裹桶状态更新,且只在需要修改 tokenslast_refill 时加锁,读取当前令牌数可不加锁(容忍短暂脏读)
  • 性能影响:锁粒度越小越好,避免把 await asyncio.sleep() 放在锁内——那会让其他协程干等

如何实现线程安全又低开销的 async 令牌桶

核心是分离「判断是否放行」和「更新桶状态」两个动作,用「先检查、再尝试更新」+ 失败重试(或直接拒绝)的策略,减少锁持有时间。

  • 使用场景:FastAPI / Starlette 中间件、aiohttp 路由装饰器、或独立的限流服务客户端
  • 关键参数:rate(每秒令牌数)、burst(最大令牌数)、refill_interval(推荐设为 1.0 / rate,但避免浮点精度误差)
  • 示例片段:
    async def _refill_tokens(self):
        now = time.time()
        if now < self.last_refill + self.refill_interval:
            return False
        # 原子更新 last_refill,避免多协程同时 refill 导致令牌溢出
        async with self._lock:
            if now >= self.last_refill + self.refill_interval:
                self.tokens = min(self.burst, self.tokens + 1)
                self.last_refill = now
                return True
        return False
    

asyncio.Lock 和 aioredis 结合做分布式限流要注意什么

单机 asyncio.Lock 只管得住本进程协程,跨实例就得靠外部存储;但 Redis 的 INCR + EXPIRE 组合不是原子的,直接拼命令会丢令牌或误限流。

Grammarly
Grammarly

Grammarly是一款在线语法纠正和校对工具,伟大的AI辅助写作工具

下载
  • 常见错误现象:高并发下 redis.exceptions.ConnectionError 频发,或同一用户在不同实例上被重复计数
  • 必须用 Lua 脚本封装 refill + check 逻辑,例如用 redis.eval 执行一段脚本,保证「读当前值 → 判断 → 写新值 → 设 TTL」全在服务端原子完成
  • 兼容性影响:Redis 6.0+ 支持 ACL 权限控制,Lua 脚本里不能调用 EVALSHA 以外的命令(除非显式授权),否则报 NOPERM
  • 参数差异:本地桶用 time.time(),Redis 桶必须用 redis.time()(即服务器时间),否则时钟漂移导致 refill 错乱

为什么 aiofiles 或 httpx 不该在限流中间件里做耗时 IO

限流本身应该是微秒级决策,一旦在里面加日志写文件、查数据库、或调第三方 API,就会把整个路由 pipeline 拖慢,甚至让限流器自己成为瓶颈。

立即学习Python免费学习笔记(深入)”;

  • 典型踩坑:在 __aenter__ 里用 aiofiles.open 记录每次请求,结果磁盘 IO 成为性能天花板
  • 正确做法:限流只做两件事——返回 True/False,和可选地更新内存/Redis 状态;审计日志、告警、指标上报全部异步解耦(比如发到 asyncio.Queue 由后台 task 消费)
  • 性能影响:实测在 FastAPI middleware 中加入一次 httpx.AsyncClient.get("https://httpbin.org/delay/0.1"),P99 延迟从 8ms 涨到 120ms+

事情说清了就结束。真正难的不是写个能跑的 async 令牌桶,而是想清楚哪些操作必须原子、哪些可以妥协、以及什么时候该放弃“精确限流”去换确定性延迟。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
什么是分布式
什么是分布式

分布式是一种计算和数据处理的方式,将计算任务或数据分散到多个计算机或节点中进行处理。本专题为大家提供分布式相关的文章、下载、课程内容,供大家免费下载体验。

391

2023.08.11

分布式和微服务的区别
分布式和微服务的区别

分布式和微服务的区别在定义和概念、设计思想、粒度和复杂性、服务边界和自治性、技术栈和部署方式等。本专题为大家提供分布式和微服务相关的文章、下载、课程内容,供大家免费下载体验。

246

2023.10.07

什么是中间件
什么是中间件

中间件是一种软件组件,充当不兼容组件之间的桥梁,提供额外服务,例如集成异构系统、提供常用服务、提高应用程序性能,以及简化应用程序开发。想了解更多中间件的相关内容,可以阅读本专题下面的文章。

180

2024.05.11

Golang 中间件开发与微服务架构
Golang 中间件开发与微服务架构

本专题系统讲解 Golang 在微服务架构中的中间件开发,包括日志处理、限流与熔断、认证与授权、服务监控、API 网关设计等常见中间件功能的实现。通过实战项目,帮助开发者理解如何使用 Go 编写高效、可扩展的中间件组件,并在微服务环境中进行灵活部署与管理。

222

2025.12.18

Python FastAPI异步API开发_Python怎么用FastAPI构建异步API
Python FastAPI异步API开发_Python怎么用FastAPI构建异步API

Python FastAPI 异步开发利用 async/await 关键字,通过定义异步视图函数、使用异步数据库库 (如 databases)、异步 HTTP 客户端 (如 httpx),并结合后台任务队列(如 Celery)和异步依赖项,实现高效的 I/O 密集型 API,显著提升吞吐量和响应速度,尤其适用于处理数据库查询、网络请求等耗时操作,无需阻塞主线程。

28

2025.12.22

Python 微服务架构与 FastAPI 框架
Python 微服务架构与 FastAPI 框架

本专题系统讲解 Python 微服务架构设计与 FastAPI 框架应用,涵盖 FastAPI 的快速开发、路由与依赖注入、数据模型验证、API 文档自动生成、OAuth2 与 JWT 身份验证、异步支持、部署与扩展等。通过实际案例,帮助学习者掌握 使用 FastAPI 构建高效、可扩展的微服务应用,提高服务响应速度与系统可维护性。

201

2026.02.06

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

675

2023.08.10

常用的数据库软件
常用的数据库软件

常用的数据库软件有MySQL、Oracle、SQL Server、PostgreSQL、MongoDB、Redis、Cassandra、Hadoop、Spark和Amazon DynamoDB。更多关于数据库软件的内容详情请看本专题下面的文章。php中文网欢迎大家前来学习。

993

2023.11.02

pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法
pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法

本专题系统整理pixiv网页版官网入口及登录访问方式,涵盖官网登录页面直达路径、在线阅读入口及快速进入方法说明,帮助用户高效找到pixiv官方网站,实现便捷、安全的网页端浏览与账号登录体验。

145

2026.02.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 22.4万人学习

Django 教程
Django 教程

共28课时 | 4.3万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.6万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号