速率限制 是用於控制資源使用量,並維持服務品質的重要機制。Go 語言以協程、頻道和 計時器 優雅地支援了速率限制。
|
|
|

package main
|
|
import (
"fmt"
"time"
)
|
|
func main() {
|
首先,我們將探討基本速率限制。假設我們想要限制處理 incoming request。我們會建立一個擁有相同名稱的頻道,使用它來提供這些 request 的服務。
|
requests := make(chan int, 5)
for i := 1; i <= 5; i++ {
requests <- i
}
close(requests)
|
這個 limiter 頻道每 200 毫秒就會接收一個值。這是我們的速率限制機制中的調節器。
|
limiter := time.Tick(200 * time.Millisecond)
|
在為每個 request 提供服務之前,阻擋來自 limiter 頻道的接收,我們就能讓自己每 200 毫秒處理一個 request。
|
for req := range requests {
<-limiter
fmt.Println("request", req, time.Now())
}
|
我們或許會想要在速率限制機制中允許簡短地 burst request,同時維持總體速率限制。我們可以透過緩衝 limiter 頻道來達成這個目標。這個 burstyLimiter 頻道將允許 burst 最多 3 個事件。
|
burstyLimiter := make(chan time.Time, 3)
|
填滿頻道以表示允許 burst。
|
for i := 0; i < 3; i++ {
burstyLimiter <- time.Now()
}
|
我們每隔 200 毫秒會嘗試在 burstyLimiter 中新增一個值,直到達到其 3 的限制為止。
|
go func() {
for t := range time.Tick(200 * time.Millisecond) {
burstyLimiter <- t
}
}()
|
現在再模擬 5 個 incoming request。前 3 個將會受惠於 burstyLimiter 的 burst 能力。
|
burstyRequests := make(chan int, 5)
for i := 1; i <= 5; i++ {
burstyRequests <- i
}
close(burstyRequests)
for req := range burstyRequests {
<-burstyLimiter
fmt.Println("request", req, time.Now())
}
}
|