fastapi用fastapi-limiter限流需显式配置redisbackend并关闭decode_responses;flask用slowapi要绑定app、处理预检请求;限流key须正确提取真实ip或token,避免sqlite并发锁,存储选型上线前必须确定。

用 fastapi-limiter 做 API 限流最省事
Python Web 框架里,FastAPI 配 fastapi-limiter 是目前最轻量、最贴合异步语义的限流方案。它底层用 aioredis 或 redis-py(同步模式下 fallback),不侵入业务逻辑,装饰器一加就生效。
常见错误是直接 pip install fastapi-limiter 后跳过 Redis 连接配置——get_redis_connection 会静默 fallback 到内存存储,压测时看似限流生效,上线后秒变失效。
- 必须显式初始化
RedisBackend并传给Limiter,哪怕只用单机 Redis:limiter = Limiter(key_func=get_remote_address, redis_connection=redis)
-
key_func默认用 IP,但真实场景常要按user_id或token限流,得自己写函数提取,别硬套默认值 - 如果用
redis-py3.5+,注意它默认开启decode_responses=True,而fastapi-limiter内部 expect bytes,会抛TypeError: sequence item 0: expected str instance—— 关掉它:redis = redis.Redis(decode_responses=False)
slowapi 在 Flask 里怎么配 rate limit
Flask 没原生异步支持,slowapi 是目前维护最勤、兼容性最好的选择。它本质是 WSGI 中间件 + 装饰器组合,和 Flask 的 request context 绑得紧,比手撸 before_request + 全局计数器靠谱得多。
典型翻车点:在蓝图(Blueprint)里加限流装饰器,却忘了在创建 Limter 实例时传 app;或者把 @limiter.limit("100/day") 错贴在类视图的方法上,没配合 @limiter.exempt 处理 OPTIONS 预检请求,导致 CORS 直接 429。
立即学习“Python免费学习笔记(深入)”;
本文档主要讲述的是Python开发网站指南;HTML是网络的通用语言,一种简单、通用的全置标记语言。它允许网页制作人建立文本与图片相结合的复杂页面,这些页面可以被网上任何其他人浏览到,无论使用的是什么类型的电脑或浏览器 Python和其他程序语言一样,有自身的一套流程控制语句,而且这些语句的语法和其它程序语言类似,都有for, if ,while 类的关键字来表达程序流程。希望本文档会给有需要的朋友带来帮助;感兴趣的朋友可以过来看看
- 初始化必须绑定 app:
limiter = Limiter(app, key_func=get_remote_address)
,不能只写Limiter(key_func=...) - 路径匹配支持通配符,比如
@limiter.limit("10/minute", key_func=lambda: request.headers.get("X-User-ID"))可实现 per-user 限流 - 测试时用
pytest+test_client,记得每次请求后调用limiter.reset(),否则测试用例之间会互相污染
为什么不用 flask-limiter 直接连 SQLite
本地开发图省事,有人试过用 flask-limiter + sqlite:///rate_limit.db,结果发现并发一高就报 Database is locked。SQLite 不支持高并发写,而限流本质是高频 incr + expire 操作,每请求至少 2 次写入。
这不是配置问题,是存储引擎选型错误。哪怕只跑单机服务,也该换 redis://localhost —— Docker 里起个 Redis 容器只要 10 秒,比调试锁冲突快十倍。
-
flask-limiter的memory存储类型只适合单元测试,进程重启即清空,无法跨 worker 生效 - 若真没法上 Redis,可用
memcached替代,flask-limiter支持memcache://,性能和原子性比 SQLite 强一个数量级 - 别信“先用 SQLite 上线,后面再切 Redis”的说法——限流规则变更、数据迁移、灰度验证全是坑,上线前就该定死存储后端
Rate limit key 提取容易漏掉 header 或 query 参数
限流 key 决定“谁被限”,写错就等于限错了人。常见疏忽是只取 request.remote_addr,但实际流量可能经过 Nginx、Cloudflare,真实 IP 在 X-Forwarded-For 或 X-Real-IP 里;或者要按 API key 限流,却忘了从 Authorization header 解析 Bearer token。
更隐蔽的问题:前端带了 ?v=1.2.3 这类无意义 query 参数,导致同一接口被当成多个 key 计数,实际 QPS 毫无约束。
- 取 IP 务必检查代理链:
def get_real_ip(): return request.headers.get("X-Forwarded-For", "").split(",")[0].strip() or request.remote_addr - 从 header 提取 API key 时,用
request.headers.get("Authorization", "").replace("Bearer ", ""),别直接切字符串,避免空格或大小写异常 - 限流 key 函数里主动过滤 query 参数,比如只保留
user_id和action:"{0}_{1}".format(get_user_id(), request.args.get("action", "default"))









