Iris限流易失效的根本原因是中间件执行顺序错位:Logger、JWT等中间件提前读取r.Body导致MaxRequestBodySize失效,且RateLimitMiddleware若未前置注册或未用Redis+Lua原子实现,会造成计数漂移、漏限与误判。

限流不是加个中间件就完事,Iris 的 MaxRequestBodySize 和自定义限流逻辑极易因执行顺序错位而完全失效。
为什么 RateLimitMiddleware 会漏掉请求
常见现象是:接口在压测时仍能被刷穿,429 Too Many Requests 响应极少出现。根本原因是限流中间件注册位置不对,或被其他中间件提前消耗了请求体。
-
Logger中间件若开启LogRequestBody: true,会在路由匹配前完整读取并缓存r.Body,后续任何基于r.Body的限流(如文件上传大小)都拿不到原始流 -
JWT或权限中间件里调用r.ParseForm(),会触发io.ReadAll(r.Body),导致 body 被清空 - 业务 handler 中直接用
json.NewDecoder(c.Request().Body).Decode(),没包装http.MaxBytesReader,限流形同虚设 -
iris.Host()分组路由后,若未在每个分组内单独注册限流中间件,子域名租户可能共享同一套限流计数器,造成误判
上传文件大小限制必须手动包装 r.Body
Iris 的 MaxRequestBodySize 配置项只在首次访问 c.Request().Body 前生效;一旦被提前读取,它就彻底失效。你必须显式用 http.MaxBytesReader 包装。
- 正确做法:写一个中间件,在所有可能读 body 的逻辑之前执行一次,且必须排在
Logger、JWT、Recover等中间件之前 - 示例中间件:
func bodyLimitMiddleware(max int64) iris.Handler { return func(ctx iris.Context) { ctx.Request().Body = http.MaxBytesReader(ctx.ResponseWriter(), ctx.Request().Body, max) ctx.Next() } } - 全局统一限流(如 ≤10MB):
app.Use(bodyLimitMiddleware(10 - 路由级差异化(如
/upload放宽到 50MB):app.Post("/upload", uploadHandler).Handle(bodyLimitMiddleware(50
Redis + Lua 实现原子化接口级限流
单纯靠内存计数器无法支撑分布式部署,必须依赖 Redis。但要注意 Lua 脚本的 key 设计和过期逻辑,否则会出现计数漂移或 key 泄露。
- key 应包含路径与 IP,避免不同接口共用同一计数器:
fmt.Sprintf("rate:%s:%s", ctx.Path(), ip) - 必须用 Lua 原子执行
INCR+EXPIRE,不能拆成两步:否则并发下第一次INCR返回 1,但EXPIRE失败,该 key 永久存在 - 注意
window.Seconds()传参类型,RedisEXPIRE接收整数秒,传浮点数会导致脚本报错ERR value is not an integer or out of range - 错误处理不能只判
err != nil,还要检查count > limit,因为 Lua 返回 0 也可能表示已超限
多维度限流要分层设计,别堆在一个中间件里
企业级场景中,单靠 IP 限流不够——用户可能走代理,奖品可能被集中爆破。必须组合接口级、用户级、奖品类三级限流。
- 接口级(通用):用上述
RateLimitMiddleware,key 为path+ip - 用户级(需鉴权后):在 JWT 解析成功后,用
ctx.Values().Get("user_id")构造 key,如fmt.Sprintf("user_rate:%s:%s", userID, ctx.Path()) - 奖品类(抽奖系统特有):key 加入奖品 ID,例如
fmt.Sprintf("prize_rate:%s:%s", prizeID, userID),配合 RedisSETNX+ 过期时间防重复提交 - 注意:三层限流不能嵌套在同一个中间件里判断,否则任一失败就中断流程;应各自独立返回状态,并由上层聚合决策是否放行
最易被忽略的是:限流 key 的生命周期管理。Redis 中大量短时效 key 若未设置 EXPIRE,或 Lua 脚本中 EXPIRE 执行失败,会导致内存持续增长,最终 OOM。上线前务必用 redis-cli --scan --pattern "rate:*" | wc -l 抽样检查 key 数量趋势。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











