限流概念
高并发系统三大利器“缓存、降级、限流
- 缓存:提升系统访问速度和增大处理容量,为相应业务增加缓存
- 降级:当服务器压力剧增时,根据业务策略降级,以释放服务资源保证业务正常
- 限流:通过对并发限速,以达到拒绝服务、排队或等待、降价等处理
限流策略
漏桶限流:每次请求时计算桶流量,超过阈值则降级请求
有一个漏桶,请求来了就像是往漏桶里注入水,桶满了舍弃请求,但是无论来多少次请求,桶都以固定的速度滴水(处理请求)
因为无论来多少流量是以固定的速度处理请求,所以不能有效的处理大量突发请求的场景
令牌桶限流:每次请求时从令牌桶里取令牌,取不到则降级请求
有一个令牌桶,以固定的速率向令牌桶中添加令牌,如果桶满了则丢弃令牌,每次请求来了就向令牌桶中取令牌,取得到就放行处理,令牌不足则拒绝请求
因为令牌桶在平时处理请求时会保持一个桶中余留很多空闲令牌的状态,则可以处理大量突发请求的场景
限流库的使用
安装限流库
| go get github.com/juju/ratelimit
|
创建令牌桶的方法
1 2 3 4 5 6 7 8 9
| func NewBucket(fillInterval time.Duration, capacity int64) *Bucket
func NewBucketWithQuantum(fillInterval time.Duration, capacity, quantum int64) *Bucket
func NewBucketWithRate(rate float64, capacity int64) *Bucket
|
取出令牌的方法
1 2 3 4 5 6 7 8 9 10 11 12
|
func (tb *Bucket) Take(count int64) time.Duration
func (tb *Bucket) TakeAvailable(count int64) int64
func (tb *Bucket) TakeMaxDuration(count int64, maxWait time.Duration) (time.Duration, bool)
func (tb *Bucket) Wait(count int64) func (tb *Bucket) WaitMaxDuration(count int64, maxWait time.Duration) bool
|
Gin中使用限流中间件
在Gin中可以将限流作为中间件注册到路由中
既可以将它注册到全局中间件,也可以将它注册到局部的路由组
1 2 3 4 5 6 7 8 9 10 11 12 13
| func RateLimiter(fillTime time.Duration, cap int64) gin.HandlerFunc { bucket := ratelimit.NewBucket(fillTime, cap) return func(c *gin.Context) { if bucket.TakeAvailable(1) < 1 { c.JSON(http.StatusOK, "rate limit...") c.Abort() return } c.Next() } }
|