如何使用Golang实现Web API限流_Golang Web流量控制技巧-Golang

time.ticker 不适合精确限流,因其仅按时间触发而忽略请求到达节奏,导致突发流量漏放;应改用 rate.limiter 实现每 ip 独立、带突发容忍的实时判断,并在分布式场景下结合 redis 粗粒度窗口与本地细粒度控制。

为什么 time.Ticker 不适合做精确限流

直接用 time.Ticker 控制每秒请求数,看似简单,但会漏掉突发流量的拦截——它只管“时间到了没”,不管“这秒已经来了多少个请求”。比如设定 QPS=10,但第 1 秒前 100ms 就涌入 12 个请求,time.Ticker 会在 1s 后才触发下一次检查,中间这 12 个请求全被放行,实际已超限。

真正可控的方式是:每个请求进来时立刻判断是否该拒绝。推荐用滑动窗口或令牌桶,而 Go 生态里最轻量、无依赖的方案是基于 golang.org/x/time/rate 的 rate.Limiter。

用 rate.Limiter 实现 per-IP 精确限流

默认的 rate.Limiter 是全局共享的,要实现按客户端 IP 限流,必须为每个 IP 维护独立实例。不能直接 map[string]*rate.Limiter 并长期持有——IP 太多会内存泄漏;也不能每次请求都新建——性能差且失去限流意义。

实用做法是用带过期的缓存(如 sync.Map + 时间戳标记)或更稳妥的 LRU 缓存(如 github.com/hashicorp/golang-lru/v2)。下面是一个基于 sync.Map 的简明实现:

var ipLimiters sync.Map // map[string]*rate.Limiter

func getLimiter(ip string) *rate.Limiter {
    if lim, ok := ipLimiters.Load(ip); ok {
        return lim.(*rate.Limiter)
    }
    // 每 IP 最大 10 QPS,允许最多 5 个请求瞬时突增(burst=5)
    lim := rate.NewLimiter(10, 5)
    ipLimiters.Store(ip, lim)
    return lim
}

func limitMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        ip := getClientIP(r)
        lim := getLimiter(ip)
        if !lim.Allow() {
            http.Error(w, "Too Many Requests", http.StatusTooManyRequests)
            return
        }
        next.ServeHTTP(w, r)
    })
}
  • rate.NewLimiter(10, 5) 表示平均 10 QPS,最多允许 5 个请求“欠账”(即突发时可先透支)
  • lim.Allow() 是非阻塞判断,返回 true 表示放行,false 表示应拒绝
  • getClientIP 需从 X-Forwarded-For 或 r.RemoteAddr 安全提取,注意代理场景下的伪造风险

当需要分布式限流时,别硬刚 Redis Lua

单机 rate.Limiter 在多实例部署下完全失效——每个节点各自计数,总流量轻松翻倍超限。此时必须引入中心化存储。但直接在每次请求里跑 Redis Lua 脚本(如 INCR + EXPIRE 组合)容易因网络延迟或 Redis 拥塞拖慢整个 API。

夏夕资源网专注于CMS网站模板,主流语言整站网站源码下载,网站建设相关教程分享,好用的软件素材整合下载,提供一站式便捷自助服务。
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需!
7. 如遇到加密压缩包,默认解压密码为"zy.lucklyus.top",如遇到无法解压的请联系管理员!
夏夕资源网-网站模板_免费源码_资源素材 » 如何使用Golang实现Web API限流_Golang Web流量控制技巧-Golang
在线时间:12:00 - 22:00
关注微信公众号:微信公众号
站长邮箱:[email protected]
  • 运营天数: 1393+
  • 资源总数: 47989+
  • 用户总数: 1+
  • 今日更新: 0+
  • 访问次数: 4016902+
  • 本周更新: 0+
  • 最后更新: 2026-03-16

本站指数

×
  • 运营天数: 1393+
  • 资源总数: 47989+
  • 用户总数: 1+
  • 今日更新: 0+
  • 访问次数: 4016902+
  • 本周更新: 0+
  • 最后更新: 2026-03-16