← 返回题目列表

FastAPI 如何做限流?接口限流常见方案有哪些?

高频 中等 第 10 / 27 题 更新于 2026/07/31
FastAPI限流Redis中间件

简化版

FastAPI 可以通过中间件、依赖、网关或 Redis 实现限流。单机内存限流简单但多实例不一致;生产常用 Redis 记录用户/IP/API 的计数或令牌桶,或者把限流放到 Nginx、API 网关、云网关层。

详细版

限流用于保护服务,避免单个用户、IP 或接口流量过大拖垮系统。常见算法有固定窗口、滑动窗口、令牌桶、漏桶。FastAPI 里可以在依赖或中间件中检查请求,再决定放行或返回 429。

if too_many_requests(user_id):
    raise HTTPException(status_code=429, detail="too many requests")

面试要强调部署形态:多 worker、多实例下,本地 dict 计数不准;分布式限流通常要 Redis 或网关统一执行。

完整版教学

一、为什么需要限流

没有限流时,一个恶意用户或异常客户端可能把接口打满。即使不是攻击,爬虫、重试风暴、前端 bug 也会制造高流量。

正常: 100 req/s
异常: 10000 req/s

限流的目标不是惩罚用户,而是保护整体可用性。

二、限流维度怎么选

可以按 IP、用户、租户、API key、接口路径限流。登录接口常按 IP + 用户名;开放 API 常按 API key;内部接口可能按服务名。

维度场景
IP防爬、防暴力请求
用户防单用户滥用
API key开放平台
路径保护重接口

维度选错会误伤或漏防。

三、固定窗口和滑动窗口

固定窗口简单:每分钟最多 100 次。但窗口边界会有突刺,例如 12:00:59 打 100 次,12:01:00 又打 100 次,两秒内 200 次。

固定窗口边界突刺:
59s: 100
60s: 100

滑动窗口更平滑,但实现复杂。Redis sorted set 可以实现滑动窗口,但成本比简单计数高。

四、令牌桶和漏桶

令牌桶按固定速率生成令牌,请求消耗令牌,桶里有令牌就放行。它允许一定突发。漏桶则按固定速率流出,更平滑。

令牌桶: 平均限速 + 允许突发
漏桶: 平滑输出

API 限流常用令牌桶,因为真实流量通常有小突发。

五、FastAPI 中放在哪里

可以放依赖里,适合按路由精细控制;也可以放中间件,适合全局控制;还可以在网关层做,减少请求进入应用。

async def rate_limit(request: Request):
    ...

@app.get("/items", dependencies=[Depends(rate_limit)])
def list_items():
    ...

网关层抗压更强,应用层能拿到业务用户信息,二者可以组合。

限流越靠前越省资源,越靠近业务越精准。

六、Redis 分布式限流要注意什么

多实例部署时,本地内存计数互不共享。Redis 可以做统一计数,但要保证操作原子性。简单 INCR + EXPIRE 要注意第一次设置过期时间,复杂算法可用 Lua 脚本。

worker A -> Redis
worker B -> Redis
worker C -> Redis

Redis 本身故障时要决定 fail-open 还是 fail-close:是放行请求保证可用,还是拒绝请求保护后端。

七、限流后的用户体验

限流不只是返回 429,还要让调用方知道什么时候重试。开放 API 可以返回 Retry-After、剩余额度、窗口重置时间;内部接口可以打日志和指标,帮助定位异常调用方。

HTTP 429
Retry-After: 30
X-RateLimit-Remaining: 0

如果没有清晰反馈,客户端可能继续疯狂重试,反而让压力更大。

八、监控和灰度

限流阈值不应拍脑袋一次定死。上线前可以先只记录不拦截,观察正常流量分布;上线后监控 429 数量、被限流用户、接口延迟和 Redis 错误率。

observe -> tune threshold -> enforce -> monitor

对核心付费用户、后台任务和普通匿名请求,也可能需要不同限流策略。

九、常见误区与追问

  • 误区:用全局 dict 限流就能生产可用。 多进程多实例不共享,重启也丢。
  • 误区:所有接口一个阈值。 登录、搜索、下单、静态查询成本不同,阈值应不同。
  • 误区:限流只防攻击。 它也防误用、重试风暴和热点流量。
  • 追问:为什么返回 429? HTTP 语义是 Too Many Requests。
  • 追问:Redis 操作为什么要原子? 并发请求会同时更新计数,非原子会放过超额请求。
  • 追问:网关限流和应用限流怎么选? 网关抗压,应用更懂用户和业务。
  • 追问:限流后如何提示重试? 可返回 Retry-After 或业务错误码。

十、加强记忆

FastAPI 限流记成“维度、算法、位置、存储”。按谁限、用什么算法、放网关还是应用、计数存在本机还是 Redis,这四个问题决定方案质量。生产多实例别靠本地 dict,关键接口返回 429 并做好监控。