如何實現限制用戶 1 分鐘內最多請求 1000 次?
在高併發場景下,如何保護你的服務不被海量請求壓垮?限流器是你的不二之選。本文將帶你使用 Go 語言,實現一個高效的限流器,限制每分鐘內用戶的最大請求次數。
限流算法的選擇
常見的限流算法有很多,例如:
-
計數器算法: 設定一個時間窗口,在窗口內對請求進行計數,超過閾值則拒絕請求。
-
漏桶算法: 將請求想象成水滴,漏桶以固定速率漏水,溢出則拒絕請求。
-
令牌桶算法: 以固定速率生成令牌放入桶中,請求需要獲取令牌才能通過,桶滿則丟棄令牌。
本文將採用計數器算法,因爲它實現簡單且性能較高,非常適合限制固定時間窗口內的請求次數。
Go 代碼實現
package main
import (
"fmt"
"sync"
"time"
)
// Limiter 定義限流器結構體
type Limiter struct {
rate int // 每分鐘請求限制
unit time.Duration // 時間單位
mutex sync.Mutex // 併發控制鎖
count int // 當前時間窗口內的請求計數
reset time.Time // 時間窗口重置時間
}
// NewLimiter 創建一個新的限流器
func NewLimiter(rate int, unit time.Duration) *Limiter {
return &Limiter{
rate: rate,
unit: unit,
mutex: sync.Mutex{},
count: 0,
reset: time.Now(),
}
}
// Allow 判斷是否允許請求通過
func (l *Limiter) Allow() bool {
l.mutex.Lock()
defer l.mutex.Unlock()
// 檢查是否需要重置時間窗口
if time.Since(l.reset) >= l.unit {
l.count = 0
l.reset = time.Now()
}
// 判斷請求是否超過限制
if l.count >= l.rate {
return false
}
// 請求計數加一
l.count++
return true
}
func main() {
// 創建一個每分鐘限制1000次請求的限流器
limiter := NewLimiter(1000, time.Minute)
// 模擬用戶請求
for i := 0; i < 1500; i++ {
if limiter.Allow() {
fmt.Println("請求", i+1, "通過")
} else {
fmt.Println("請求", i+1, "被限流")
}
time.Sleep(time.Millisecond * 10) // 模擬請求間隔
}
}
代碼解析
-
Limiter 結構體: 存儲限流器相關信息,包括每分鐘請求限制、時間單位、併發控制鎖、當前請求計數和時間窗口重置時間。
-
NewLimiter 函數: 創建一個新的限流器實例,並初始化相關參數。
-
Allow 函數: 判斷是否允許請求通過。首先獲取鎖,確保併發安全。然後檢查是否需要重置時間窗口,如果需要則重置計數和時間。接着判斷請求是否超過限制,超過則返回 false,否則計數加一併返回 true。
-
main 函數: 創建一個限流器實例,並模擬用戶請求。
總結
本文介紹了使用 Go 語言實現一個簡單的限流器的過程,並詳細解釋了代碼邏輯。你可以根據實際需求,調整限流參數或選擇更復雜的限流算法。合理使用限流器,可以有效保護你的服務免受流量衝擊,提高服務的穩定性和可靠性。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/c3qr-XUhZZUyzgHlMZEwzw