令牌桶算法
令牌桶算法(Token Bucket)随着时间流逝, 系统会按恒定1/QPS时间间隔(如果QPS=100, 则间隔是10ms)往桶里加入Token, 如果桶已经满了就不再加了。新请求来临时, 会各自拿走一个Token, 如果没有Token可拿了就阻塞或者拒绝服务.
限流器 rate 原理与上图的令牌桶类似。
限流器 rate 的用法和实现逻辑
官方代码库 github.com/golang/time,限流器主要用来限制请求速率,保护服务,防止服务过载。
NewLimiter
1 | func NewLimiter(r Limit, b int) *Limiter |
构造限流器,参数说明:
r
: 令牌桶每秒可以产生r
个 token。b
: 令牌桶的大小。
Reserve/ReserveN
- 获取一个预定对象
r
,表示调用者需要等待的相关信息(如,是否可以处理、何时可以处理等等),调用者可根据r
自行决定处理逻辑。 - 如下 case 返回 false:
1). 请求令牌数n
超过桶容量
1 | func (lim *Limiter) Reserve() *Reservation |
用法:
1 | // Usage example: |
实现逻辑
Allow/AllowN
- 截止到某一时刻,是否可以从桶中获取 N 个令牌。如果可以,消费 n 个 token 并返回 true;否则返回 false。
- 按照频率限制执行,超过频率限制时丢弃或者跳过
1 | func (lim *Limiter) Allow() |
Allow 是 AllowN(time. Now(), 1) 的简写。
实现逻辑
实现逻辑与 ReserveN
相同,仅使用预定对象的成功状态,即:
1 | return lim.reserveN(now, n, 0).ok |
Wait/WaitN
- 阻塞等待,可自定义等待时间(超时自动取消)。
- 如下 case 会报 error:
1). 请求令牌数n
超过桶容量
2). 请求被取消
3). 等待超时
1 | func (lim *Limiter) Wait(ctx context.Context) (err error) |
Wait 是 WaitN(ctx, 1) 的简写。
实现逻辑
SetLimit/SetLimitAt
令牌桶限流频率设置。
SetBurst/SetBurstAt
令牌桶容量设置。
引用