网易首页 > 网易号 > 正文 申请入驻

FastAPI用户把10行代码变成限流神器

0
分享至


你的API每秒能扛住多少请求?这个数字很多开发者直到被刷量攻击时才真正关心。2023年Cloudflare统计,应用层DDoS攻击同比增长了67%,而大多数初创团队的API连基础的流量控制都没做。

限流(Rate Limiting)不是什么新鲜概念,但实现方式千差万别。固定窗口计数器简单粗暴,却在整点重置时容易被瞬间击穿;滑动窗口日志精确,内存开销却让人肉疼。Token Bucket(令牌桶)算法在这两者之间找到了一个微妙的平衡点——允许突发流量,同时守住长期吞吐的底线。

今天这篇不是调包教程。我们用纯Python手搓一个Token Bucket限流器,塞进FastAPI的中间件,再给它加上按用户区分的追踪能力。最后你会拿到一段可以直接复制到生产环境的代码。

Token Bucket的工作原理:一个会自己续杯的桶

想象一个容量固定的桶,桶里装着令牌。每个请求进来时,必须从桶里拿走一枚令牌才能通过。桶空了?请求直接吃429(Too Many Requests)。

关键设计在于"续杯"机制:无论有没有请求进来,系统都会以固定速率往桶里加令牌,直到装满为止。这意味着你可以瞬间爆发——比如桶容量10,你可以一口气打10个请求——但爆发后必须等令牌慢慢恢复,才能继续。

两个参数决定一切:capacity(桶容量)控制突发上限,refill_rate(每秒补充令牌数)决定长期吞吐量。

对比其他算法,Token Bucket的优势很明显。固定窗口在每分钟重置时,恶意用户可以在59秒和01秒各打一波,实际吞掉两倍配额;滑动窗口没这个问题,但需要记录每个请求的时间戳,内存随流量线性增长。Token Bucket只用两个变量(当前令牌数、上次补充时间),O(1)空间复杂度搞定一切。


手搓核心:一个不到50行的Python类

开始写代码。我们需要一个类来管理每个用户的令牌桶状态。核心逻辑只有三件事:初始化时设置容量和补充速率;每次请求时检查并扣减令牌;按时间自动补充。

关键点在于线程安全。FastAPI跑在异步环境里,多个请求可能同时操作同一个桶。这里用asyncio.Lock保证原子性——检查令牌和扣减必须一气呵成,否则会出现超卖。

代码结构很直白:__init__里存capacity、refill_rate、tokens(当前数量)、last_update(上次补充时间戳)、还有一把锁。consume方法先算距离上次更新过了多久,按refill_rate补充令牌(不超过capacity),然后判断够不够扣。

补充令牌的计算要注意浮点数精度。直接用time.time()的差值乘refill_rate,结果可能带小数。这里选择保留小数部分的令牌——比如0.5个令牌虽然不能让请求通过,但累积到1.0时就可以。这种"信用"机制让长期平均速率严格等于refill_rate,避免整数取整带来的系统性偏差。

塞进FastAPI:中间件实现按用户限流

单个桶不够,生产环境需要按用户区分。最简单的方案是用API Key或者用户ID做键,每个键对应一个TokenBucket实例。中间件里先识别用户,再找对应的桶,最后决定是否放行。

用户识别策略取决于你的认证方式。如果用了OAuth2,可以从Authorization头解析;如果是内部服务,X-API-Key更常见。这里演示一个通用方案:优先查自定义头, fallback到IP地址。注意IP不能直接用request.client.host——经过反向代理后这个值可能是127.0.0.1,要按X-Forwarded-For链取第一个非内网地址。


中间件的结构遵循ASGI规范。外层函数接收app,返回一个async def middleware(request, call_next)的协程。内部维护一个全局字典buckets,键是用户标识,值是TokenBucket实例。字典访问也要加锁,防止并发创建重复实例。

限流触发时,标准做法是返回429状态码,并在响应头里告知客户端限制详情。RFC 6585定义了几个标准头:X-RateLimit-Limit(总配额)、X-RateLimit-Remaining(剩余)、X-RateLimit-Reset(重置时间)。虽然这些头是"X-"前缀的自定义扩展,但GitHub、Twitter等主流平台都在用,已经形成事实标准。

我们的实现会在响应头里注入这三个值。Reset时间戳的计算稍 tricky:用当前令牌缺口除以refill_rate,向上取整到秒。客户端拿到后可以据此做退避重试。

测试与调参:别让限流变成误伤

代码写完需要验证。写个简单的脚本,用httpx或者aiohttp并发打请求,观察429出现的时机是否符合预期。

调参是门手艺。capacity设太小,正常用户的批量操作会被误杀;设太大,又失去保护作用。一个经验法则:capacity至少覆盖用户单次交互的最大请求数。比如你的页面加载需要5个API调用,那capacity不能低于5。refill_rate则根据业务峰值定,日常流量的2-3倍通常够用。

还要考虑冷启动问题。新用户的桶是满的,这意味着攻击者可以不断换身份来绕过限制。配合API Key的申请审核、或者IP级别的二级限流,才能堵住这个口子。

存储层也有优化空间。目前的实现把桶状态存在内存里,服务重启就清零,多实例部署时各管各的。要解决这个问题,需要把状态外置到Redis,用Lua脚本保证检查-扣减的原子性。那又是另一个故事了。

你的API现在能扛住多少QPS?如果还没测过,建议今晚就压一压。毕竟刷量攻击不会提前打招呼,而第一封用户投诉邮件往往比监控告警来得更早。

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
聊聊纪委的组织架构

聊聊纪委的组织架构

野望谷研究社
2026-03-29 19:24:45
《西游记》中的10个冷知识,你都知道吗?

《西游记》中的10个冷知识,你都知道吗?

北梦一
2026-03-30 11:32:41
5万亿网贷行业,迎来最强监管

5万亿网贷行业,迎来最强监管

中国新闻周刊
2026-03-29 21:25:07
每一口都可能伤害心脏!JACC最新:过量摄入这些食品,心血管风险恐增67%

每一口都可能伤害心脏!JACC最新:过量摄入这些食品,心血管风险恐增67%

医诺维
2026-03-29 16:14:51
上圆下宽中间窄,粗中有细才是御姐

上圆下宽中间窄,粗中有细才是御姐

飛娱日记
2026-03-23 09:44:55
中韩关系有变,总理不来华参会,盯上蒙古国矿产,要和中国抢资源

中韩关系有变,总理不来华参会,盯上蒙古国矿产,要和中国抢资源

阿腩讲娱乐
2026-03-30 10:31:59
离谱!苹果折叠屏要卖2000美元?折痕没取消,而取消Face ID?

离谱!苹果折叠屏要卖2000美元?折痕没取消,而取消Face ID?

数码Antenna
2026-03-30 11:49:55
张老师的经纪人万霞说:

张老师的经纪人万霞说:

陈意小可爱
2026-03-30 11:50:08
律师解读单依纯被指侵权演唱《李白》事件:或面临20万到50万元赔偿

律师解读单依纯被指侵权演唱《李白》事件:或面临20万到50万元赔偿

封面新闻
2026-03-30 12:29:02
2026年中国房地产,大概率要进入“躺平时代”,房奴时代正在落幕

2026年中国房地产,大概率要进入“躺平时代”,房奴时代正在落幕

流苏晚晴
2026-03-29 16:21:16
历史一刻!张雪机车WSBK夺冠:中国制造终结欧美日垄断。

历史一刻!张雪机车WSBK夺冠:中国制造终结欧美日垄断。

趣味萌宠的日常
2026-03-29 19:02:48
22+22+20!索要大合同!勇士又留不住了

22+22+20!索要大合同!勇士又留不住了

篮球教学论坛
2026-03-29 13:24:24
向华强谈张雪峰突然离世,直言其饮食不健康,重油重盐有大问题

向华强谈张雪峰突然离世,直言其饮食不健康,重油重盐有大问题

娱乐E君
2026-03-27 12:47:59
欧洲人在性方面有多开放?德国再创历史!女厕所、女浴室随便进了

欧洲人在性方面有多开放?德国再创历史!女厕所、女浴室随便进了

西楼知趣杂谈
2026-03-24 14:38:30
中共甘肃省委组织部关于对王娟等干部任前公示的公告

中共甘肃省委组织部关于对王娟等干部任前公示的公告

精彩武威
2026-03-30 09:09:43
工程局突发通知:考勤截止,各谋生路!

工程局突发通知:考勤截止,各谋生路!

黯泉
2026-03-29 20:08:55
到底多少钱才能躺平?157万够吗?评论区炸锅…

到底多少钱才能躺平?157万够吗?评论区炸锅…

慧翔百科
2026-03-30 11:46:35
中东危机只是小菜?更大危机还在后面,外媒:中国将彻底颠覆战场

中东危机只是小菜?更大危机还在后面,外媒:中国将彻底颠覆战场

叹知
2026-03-29 18:13:46
大年三十婆婆做完十菜一汤刚要上桌,被我一脚踹开:让你坐了吗?

大年三十婆婆做完十菜一汤刚要上桌,被我一脚踹开:让你坐了吗?

卡西莫多的故事
2026-03-30 09:29:54
回加拿大生活的大山,60岁须发皆白很沧桑,重庆妻子仍风韵犹存

回加拿大生活的大山,60岁须发皆白很沧桑,重庆妻子仍风韵犹存

素衣读史
2026-03-25 21:05:22
2026-03-30 13:03:00
闪存猎手
闪存猎手
全网蹲好价的野生捕手,算力与羊毛都不可辜负。
433文章数 1关注度
往期回顾 全部

科技要闻

DeepSeek性能异常问题已解决,服务恢复

头条要闻

牛弹琴:伊朗越打越聪明了 一场更猛烈的风暴即将到来

头条要闻

牛弹琴:伊朗越打越聪明了 一场更猛烈的风暴即将到来

体育要闻

绝杀卫冕冠军后,他单手指天把胜利献给父亲

娱乐要闻

单依纯凌晨发长文道歉!李荣浩再回应

财经要闻

油价冲击,有些亚洲货币先扛不住了!

汽车要闻

理想i9要来了!外形似小号MEGA 能冲击高端纯电市场?

态度原创

旅游
教育
家居
时尚
艺术

旅游要闻

相约文旅盛会 发现宝藏山东|走进山东古建筑博物馆

教育要闻

宠物式育儿,必然养出废物!

家居要闻

东方法式美学 现代简约

来到1980的周也,好毛利兰

艺术要闻

600 年前的「产亡孤魂」,藏着中国女性最痛的记忆

无障碍浏览 进入关怀版