如何實現限制用戶 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) // 模擬請求間隔
 }
}

代碼解析

  1. Limiter 結構體: 存儲限流器相關信息,包括每分鐘請求限制、時間單位、併發控制鎖、當前請求計數和時間窗口重置時間。

  2. NewLimiter 函數: 創建一個新的限流器實例,並初始化相關參數。

  3. Allow 函數: 判斷是否允許請求通過。首先獲取鎖,確保併發安全。然後檢查是否需要重置時間窗口,如果需要則重置計數和時間。接着判斷請求是否超過限制,超過則返回 false,否則計數加一併返回 true。

  4. main 函數: 創建一個限流器實例,並模擬用戶請求。

總結

本文介紹了使用 Go 語言實現一個簡單的限流器的過程,並詳細解釋了代碼邏輯。你可以根據實際需求,調整限流參數或選擇更復雜的限流算法。合理使用限流器,可以有效保護你的服務免受流量衝擊,提高服務的穩定性和可靠性。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/c3qr-XUhZZUyzgHlMZEwzw