Debug客栈

Recent content on Debug客栈

马上订阅 Debug客栈 RSS 更新: https://blog.debuginn.com/index.xml

Go 标准库 限流器 time/rate 设计与实现

2020年8月24日 19:35
Featured image of post Go 标准库 限流器 time/rate 设计与实现

限流器是后台服务中十分重要的组件,在实际的业务场景中使用居多,其设计在微服务、网关、和一些后台服务中会经常遇到。限流器的作用是用来限制其请求的速率,保护后台响应服务,以免服务过载导致服务不可用现象出现。

限流器的实现方法有很多种,例如 Token Bucket、滑动窗口法、Leaky Bucket等。

在 Golang 库中官方给我们提供了限流器的实现golang.org/x/time/rate,它是基于令牌桶算法(Token Bucket)设计实现的。

令牌桶算法

令牌桶设计比较简单,可以简单的理解成一个只能存放固定数量雪糕?的一个冰箱,每个请求可以理解成来拿雪糕的人,有且只能每一次请求拿一块?,那雪糕拿完了会怎么样呢?这里会有一个固定放雪糕的工人,并且他往冰箱里放雪糕的频率都是一致的,例如他 1s 中只能往冰箱里放 10 块雪糕,这里就可以看出请求响应的频率了。

令牌桶设计概念:

  • 令牌:每次请求只有拿到 Token 令牌后,才可以继续访问;
  • :具有固定数量的桶,每个桶中最多只能放设计好的固定数量的令牌;
  • 入桶频率:按照固定的频率往桶中放入令牌,放入令牌不能超过桶的容量。

也就是说,基于令牌桶设计算法就限制了请求的速率,达到请求响应可控的目的,特别是针对于高并发场景中突发流量请求的现象,后台就可以轻松应对请求了,因为到后端具体服务的时候突发流量请求已经经过了限流了。

具体设计

限流器定义

1
2
3
4
5
6
7
8
type Limiter struct {
 mu sync.Mutex // 互斥锁(排他锁)
 limit Limit // 放入桶的频率 float64 类型
 burst int // 桶的大小
 tokens float64 // 令牌 token 当前剩余的数量
 last time.Time // 最近取走 token 的时间
 lastEvent time.Time // 最近限流事件的时间
}

limit、burst 和 token 是这个限流器中核心的参数,请求并发的大小在这里实现的。

在令牌发放之后,会存储在 Reservation 预约对象中:

1
2
3
4
5
6
7
type Reservation struct {
 ok bool // 是否满足条件分配了 token
 lim *...

剩余内容已隐藏

查看完整文章以阅读更多