如何用Go语言编写一个高效的限流器(Rate Limiter)代码示例?

2026-04-30 12:511阅读0评论SEO资源
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计1083个文字,预计阅读时间需要5分钟。

如何用Go语言编写一个高效的限流器(Rate Limiter)代码示例?

Go 标准库不自带限流器,但官方维护的 time/rate 包已足够健壮、线程安全,并基于令牌桶(token bucket)模型,能应对突发流量,实现平滑限流。无需自行编写计数器或时间窗口等,以免引入漏桶、竞争、时钟漂移、重置逻辑等问题。

常见错误是把 Limiter 当成“每秒只允许 N 次调用”的开关,其实它更像一个带容量的水桶:每次 Allow()Reserve() 都尝试取一个令牌,桶会按固定速率(rate.Limit)自动填充,满了就丢弃新令牌。

  • rate.Every(100 * time.Millisecond) 表示每 100ms 补 1 个令牌,等价于 10 QPS
  • 初始化时第二个参数是桶容量(burst),设为 1 就完全削平;设为 5 则允许短时 5 次连发
  • 不要在 HTTP handler 里反复 new(rate.Limiter),应复用单例或按租户/路径分实例

Allow()Reserve() 怎么选

Allow() 是最简接口:返回 bool,true 表示“此刻有令牌可取”,false 就该拒绝。适合无延迟容忍的场景(如 API 鉴权前置拦截)。

Reserve() 返回 *rate.Reservation,能告诉你“如果现在取,要等多久”,适合需要排队或预估延迟的逻辑(比如后台任务调度)。

阅读全文
标签:Go

本文共计1083个文字,预计阅读时间需要5分钟。

如何用Go语言编写一个高效的限流器(Rate Limiter)代码示例?

Go 标准库不自带限流器,但官方维护的 time/rate 包已足够健壮、线程安全,并基于令牌桶(token bucket)模型,能应对突发流量,实现平滑限流。无需自行编写计数器或时间窗口等,以免引入漏桶、竞争、时钟漂移、重置逻辑等问题。

常见错误是把 Limiter 当成“每秒只允许 N 次调用”的开关,其实它更像一个带容量的水桶:每次 Allow()Reserve() 都尝试取一个令牌,桶会按固定速率(rate.Limit)自动填充,满了就丢弃新令牌。

  • rate.Every(100 * time.Millisecond) 表示每 100ms 补 1 个令牌,等价于 10 QPS
  • 初始化时第二个参数是桶容量(burst),设为 1 就完全削平;设为 5 则允许短时 5 次连发
  • 不要在 HTTP handler 里反复 new(rate.Limiter),应复用单例或按租户/路径分实例

Allow()Reserve() 怎么选

Allow() 是最简接口:返回 bool,true 表示“此刻有令牌可取”,false 就该拒绝。适合无延迟容忍的场景(如 API 鉴权前置拦截)。

Reserve() 返回 *rate.Reservation,能告诉你“如果现在取,要等多久”,适合需要排队或预估延迟的逻辑(比如后台任务调度)。

阅读全文
标签:Go