限流,顾名思义,限制用户请求流量,避免大规模并发导致系统宕机。
令牌管理员以恒定的速率向令牌桶里放置一个令牌。如果桶满,就丢弃令牌。
请求到达时,都要先去令牌桶里取一个令牌,如果取到令牌,则进行后续业务逻辑操作,否则直接返回。
package main
import (
"fmt"
"time"
)
const (
rate = 2 // 限制令牌发送速率
capacity = 1024 // 令牌桶的容量
reqNum = 10 // 并发到达的请求数
)
func main() {
bucket := make(chan struct{}, capacity)
go func() {
ticker := time.NewTicker(time.Second / rate) // tps=rate
defer ticker.Stop()
for range ticker.C {
select {
case bucket <- struct{}{}: // 令牌桶未满
default: // 令牌桶已满
}
}
}()
for i := 0; i < reqNum; i++ {
go func(i int) {
for {
select {
case <-bucket: // 获取令牌
fmt.Printf("[%d]: get a token, perform subsequent service processing\n", i)
default:
}
}
}(i)
}
select {}
}