golang 实现每秒限流
时间: 2023-07-26 15:23:31 浏览: 71
可以使用滑动窗口算法实现每秒限流。具体实现步骤如下:
1. 初始化一个固定大小的窗口,比如 1 秒,将窗口中的每个时间段划分为若干个小时间段。
2. 维护一个队列,存储每个小时间段的请求数量。
3. 每当有请求到达时,将当前时间所对应的小时间段的请求数量加 1。
4. 每秒钟定时清空队列,将窗口往右移动一个小时间段,把队列中的值加起来,得到当前窗口中的总请求数量。
5. 如果总请求数量超过了限制值,拒绝当前请求,否则允许当前请求通过。
下面是一个使用 golang 实现的每秒限流的示例代码:
```
package main
import (
"fmt"
"sync"
"time"
)
type SlidingWindow struct {
windowSize int // 窗口大小,单位为秒
bucketSize int // 每个小时间段的大小,单位为毫秒
buckets []int // 存储每个小时间段的请求数量
currentIndex int // 当前时间所对应的小时间段的索引
mutex sync.RWMutex // 读写锁
}
func NewSlidingWindow(windowSize int, bucketSize int) *SlidingWindow {
return &SlidingWindow{
windowSize: windowSize,
bucketSize: bucketSize,
buckets: make([]int, windowSize*1000/bucketSize),
currentIndex: 0,
}
}
func (sw *SlidingWindow) AddRequest() bool {
sw.mutex.Lock()
defer sw.mutex.Unlock()
now := time.Now().UnixNano() / 1e6
index := (now / int64(sw.bucketSize)) % int64(len(sw.buckets))
if index != sw.currentIndex {
sw.buckets[index] = 0
sw.currentIndex = int(index)
}
count := 0
for _, value := range sw.buckets {
count += value
}
if count >= sw.windowSize*1000/sw.bucketSize {
return false
}
sw.buckets[index]++
return true
}
func main() {
sw := NewSlidingWindow(1, 100)
for i := 0; i < 10; i++ {
go func() {
for {
if sw.AddRequest() {
fmt.Println("allow")
} else {
fmt.Println("reject")
}
time.Sleep(time.Millisecond * 100)
}
}()
}
select {}
}
```
在上面的示例代码中,NewSlidingWindow 函数用于创建一个新的滑动窗口,windowSize 参数表示窗口大小,bucketSize 参数表示每个小时间段的大小,单位分别为秒和毫秒。AddRequest 函数用于添加一个新的请求,如果当前窗口中的总请求数量超过了限制值,就返回 false,否则返回 true。最后在主函数中创建了 10 个协程并发地发送请求,测试每秒限流的效果。