Iris 框架需自行实现限流,v12.2.0+ 提供内存级 iris.Limiter(令牌桶),支持按路径或自定义 key(如 IP)限流;分布式场景须用 Redis + Lua 原子计数,key 应含客户端标识(推荐 token/IP+UA 组合);防刷须与签名、时间戳校验联动,且限流中间件必须置于签名验证之后。

Iris 框架本身不内置限流中间件,但可以通过组合 iris.Limiter(v12.2.0+)、自定义中间件 + Redis 或内存计数器快速实现接口防刷,关键在于控制单位时间内的请求频次,且必须区分客户端标识(如 IP、User-Agent、Token)。
用 iris.Limiter 做基础速率限制
Iris 从 v12.2.0 起提供了轻量级限流器 iris.Limiter,适合单机场景、低并发防护。它基于令牌桶算法,但只在内存中维护状态,不跨进程共享。
- 默认按请求路径(
ctx.Request().URL.Path)限流,若需按 IP 区分,得手动传入 key —— 必须自己提取ctx.RemoteAddr()或X-Forwarded-For头 - 初始化时指定最大请求数和窗口时间,例如
iris.Limiter(10, 60*time.Second)表示每分钟最多 10 次 - 它会在响应头写入
X-RateLimit-Limit、X-RateLimit-Remaining等字段,方便前端感知 - 触发限流时返回 HTTP 429,默认不带 body,如需自定义响应,得包装一层中间件捕获错误
用 Redis 实现分布式接口防刷
生产环境多实例部署时,必须依赖 Redis 做全局计数。核心逻辑是:对每个客户端标识生成唯一 key(如 rate:ip:192.168.1.100:/api/v1/login),用 INCR + EXPIRE 原子操作完成计数与过期设置。
- 不要直接用
SET key value EX 60 NX,因为无法原子递增;推荐用 Lua 脚本封装INCR和EXPIRE两步,避免竞态 - key 设计必须包含可区分客户端的字段:纯 IP 不可靠(NAT 网关下会误杀),建议组合
X-Real-IP+User-Agent的哈希,或优先使用登录态中的Authorizationtoken 解析出用户 ID - Iris 中注册中间件时,通过
ctx.Values().Set()可临时存取解析结果,避免重复计算 - Redis 连接建议用连接池(如
github.com/go-redis/redis/v8),超时设为500ms,失败时应降级为本地限流或放行,不能阻塞主流程
防刷策略要配合签名与时间戳校验
单纯限流防不住重放攻击。真实业务中,必须和参数签名(sign)、时间戳(timestamp)校验联动,否则黑客可批量构造不同参数绕过频率限制。
- 所有防刷中间件应在签名验证 之后 执行,否则非法请求也会被计数,造成资源浪费甚至被耗尽
- timestamp 必须在服务端校验,允许误差一般设为
≤ 300s;若超时,直接拒绝,不进限流逻辑 - sign 计算必须包含 timestamp 字段,且服务端重新拼接参数再算一次,比对一致才继续——这是防篡改和防重放的底线
- 如果用 JWT,可把客户端 IP、User-Agent、timestamp 写入 payload 并签名,省去单独校验步骤,但要注意 token 过期时间不宜过长
真正难的是 client 标识的准确性与降级策略的平衡:IP 易伪造,token 需鉴权前置,User-Agent 可被修改。线上建议三者加权组合,并始终保留内存限流兜底,避免 Redis 故障时整个接口不可用。


















