iris无内置throttle中间件,需用iris.limiter工厂函数绑定路由,必须为每个ip动态创建rate.limiter实例并用sync.map缓存,避免全局复用;生产环境须结合redis实现分布式限流,且限流应精准作用于敏感业务路径而非全局限流。

用 iris.Limiter 中间件直接绑定路由
Iris 没有内置类似 Laravel throttle 那样开箱即用的限流中间件,但提供了 iris.Limiter 工厂函数,可快速为单个路由或分组挂载基于内存或 Redis 的限流逻辑。它底层封装了 golang.org/x/time/rate,默认使用令牌桶算法。
关键点在于:必须显式传入 rate.Limiter 实例,不能只写字符串参数;且该实例需按请求维度(如 IP)动态生成,否则所有请求共用一个桶,失去限流意义。
- 在路由注册时调用
.Handler(iris.Limiter(limiter)),不是.Use() - 若用内存存储(默认),多进程部署时各进程独立计数,不一致;生产环境务必搭配 Redis
- IP 获取依赖
ctx.RemoteAddr(),经 Nginx 转发后需手动从X-Forwarded-For提取
按客户端 IP 构造唯一 rate.Limiter 实例
直接复用同一个 rate.Limiter 对象会导致所有请求被统一限制,必须为每个 IP 动态创建或复用其专属实例。常见错误是把 rate.NewLimiter(10, 20) 写死在全局变量里。
推荐用 sync.Map 缓存已创建的限流器,避免高频新建 goroutine 开销:
var limiters = sync.Map{} // key: ip, value: *rate.Limiter
func getLimiter(ip string) *rate.Limiter {
if limiter, ok := limiters.Load(ip); ok {
return limiter.(*rate.Limiter)
}
limiter := rate.NewLimiter(5, 10) // 每秒 5 令牌,桶容量 10
limiters.Store(ip, limiter)
return limiter
}
app.Get("/api/data", func(ctx iris.Context) {
ip := ctx.RemoteAddr()
if ctx.Request().Header.Get("X-Forwarded-For") != "" {
ip = strings.Split(ctx.Request().Header.Get("X-Forwarded-For"), ",")[0]
}
if !getLimiter(ip).Allow() {
ctx.StatusCode(429)
ctx.WriteString("Too many requests")
return
}
ctx.JSON(map[string]string{"status": "ok"})
})
用 Redis 实现分布式限流(跨进程/多实例)
当服务部署多个实例,或使用 PM2、supervisord 管理多进程时,内存限流完全失效。此时必须借助 Redis 原子操作模拟滑动窗口或固定窗口计数。
当代理已经知道网站路由或内容URL,并且在启动前需要有效的sitemap XML、sitemap索引或robots.txt引用时,请使用sitemap。这是一个发布构件技能,而不是爬虫或SEO平台。
Iris 本身不提供 Redis 限流中间件,需自行封装。核心逻辑是:INCR + EXPIRE 组合保证键存在性与自动过期,再用 GET 判断是否超限。
- 键名建议含时间戳粒度,例如
rate:ip:192.168.1.100:2026092018(小时级)或...:202609201852(分钟级) - 不要用 Lua 脚本一次性完成全部逻辑——Iris 的
redis客户端(如github.com/go-redis/redis/v8)已支持原子 pipeline - 注意 Redis 连接池配置,高并发下连接耗尽比限流失效更致命
为什么不能直接用 app.UseGlobal() 全局限流?
全局中间件对所有路由生效,包括健康检查、静态资源、Swagger 页面等,极易误伤。比如 /healthz 被 Prometheus 每 15 秒轮询一次,若限流设为 “每分钟 3 次”,服务立刻不可用。
真正需要限流的是业务敏感路径,例如:
-
/api/v1/user/:id(防 ID 枚举) -
/admin/export(防数据批量导出) -
/login(防暴力破解)
这些路径应单独绑定限流中间件,且阈值差异化设置:登录接口建议 5 次/分钟,导出接口建议 1 次/小时,用户详情接口可设为 30 次/分钟。










