1

使用场景为防止并发量突然增高时,服务器无法承受,保证了QPS的上限值。
主要分为漏桶和令牌桶:

漏桶是指我们有一个一直装满了水的桶,每过固定的一段时间即向外漏一滴水。如果你接到了这滴水,那么你就可以继续服务请求,如果没有接到,那么就需要等待下一滴水。

令牌桶则是指匀速向桶中添加令牌,服务请求时需要从桶中获取令牌,令牌的数目可以按照需要消耗的资源进行相应的调整。如果没有令牌,可以选择等待,或者放弃。

package main

import (
    "net/http"
    "time"

    "github.com/gin-gonic/gin"
    "github.com/juju/ratelimit"
)

func RateLimitMiddleware(fillInterval time.Duration, cap, quantum int64) gin.HandlerFunc {
    bucket := ratelimit.NewBucketWithQuantum(fillInterval, cap, quantum)
    return func(c *gin.Context) {
        if bucket.TakeAvailable(1) < 1 {
            c.String(http.StatusForbidden, "rate limit...")
            c.Abort()
            return
        }
        c.Next()
    }
}

func main() {
    r := gin.Default()
    gin.ForceConsoleColor()
    r.Use(RateLimitMiddleware(time.Second, 100, 100)) //初始100,每秒放出100
    r.GET("/", func(c *gin.Context) {
        c.String(http.StatusOK, "golang ~")
    })
    r.Run(":8080")
}

1、认的令牌桶,fillInterval 指每过多长时间向桶里放一个令牌,capacity 是桶的容量,超过桶容量的部分会被直接丢弃。桶初始是满的

func NewBucket(fillInterval time.Duration, capacity int64) *Bucket

2、和普通的 NewBucket() 的区别是,每次向桶中放令牌时,是放 quantum 个令牌,而不是一个令牌。

func NewBucketWithQuantum(fillInterval time.Duration, capacity, quantum int64) *Bucket

3、按照提供的比例,每秒钟填充令牌数。例如 capacity 是100,而 rate 是 0.1,那么每秒会填充10个令牌。

func NewBucketWithRate(rate float64, capacity int64) *Bucket

goper
413 声望26 粉丝

go 后端开发