概念簡介
速率限製(英) 是一個重要的控製服務資源利用和質量的途徑。Go 通過 Go 協程、通道和打點器優美的支持了速率限製。
例程代碼
package main
import "time"
import "fmt"
func main() {
// 首先我們將看一下基本的速率限製。假設我們想限製我們
// 接收請求的處理,我們將這些請求發送給一個相同的通道。
requests := make(chan int, 5)
for i := 1; i <= 5; i++ {
requests <- i
}
close(requests)
// 這個 `limiter` 通道將每 200ms 接收一個值。這個是
// 速率限製任務中的管理器。
limiter := time.Tick(time.Millisecond * 200)
// 通過在每次請求前阻塞 `limiter` 通道的一個接收,我們限製
// 自己每 200ms 執行一次請求。
for req := range requests {
<-limiter
fmt.Println("request", req, time.Now())
}
// 有時候我們想臨時進行速率限製,並且不影響整體的速率控製,
// 我們可以通過[通道緩衝](channel-buffering.html)來實現。
// 這個 `burstyLimiter` 通道用來進行 3 次臨時的脈衝型速率限製。
burstyLimiter := make(chan time.Time, 3)
// 想將通道填充需要臨時改變3次的值,做好準備。
for i := 0; i < 3; i++ {
burstyLimiter <- time.Now()
}
// 每 200 ms 我們將添加一個新的值到 `burstyLimiter`中,
// 直到達到 3 個的限製。
go func() {
for t := range time.Tick(time.Millisecond * 200) {
burstyLimiter <- t
}
}()
// 現在模擬超過 5 個的接入請求。它們中剛開始的 3 個將
// 由於受 `burstyLimiter` 的“脈衝”影響。
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())
}
}
執行&輸出
# 運行程序,我們看到第一批請求意料之中的大約每 200ms 處理一次。
$ go run rate-limiting.go
request 1 2012-10-19 00:38:18.687438 +0000 UTC
request 2 2012-10-19 00:38:18.887471 +0000 UTC
request 3 2012-10-19 00:38:19.087238 +0000 UTC
request 4 2012-10-19 00:38:19.287338 +0000 UTC
request 5 2012-10-19 00:38:19.487331 +0000 UTC
# 第二批請求,我們直接連續處理了 3 次,這是由於這個“脈衝”
# 速率控製,然後大約每 200ms 處理其餘的 2 個。
request 1 2012-10-19 00:38:20.487578 +0000 UTC
request 2 2012-10-19 00:38:20.487645 +0000 UTC
request 3 2012-10-19 00:38:20.487676 +0000 UTC
request 4 2012-10-19 00:38:20.687483 +0000 UTC
request 5 2012-10-19 00:38:20.887542 +0000 UTC
課程導航
學習上一篇:Go語言教程:工作池 學習下一篇:Go語言教程:原子計數器
相關資料
本例程github源代碼:https://github.com/xg-wang/gobyexample/tree/master/examples/rate-limiting