赞
踩
速率限制 (英) 是 一个重要的控制服务资源利用和质量的途径。
Go 中可以通过 Go 协程、通道和打点器来支持了速率限制。
// rate-limiting.go package main import ( "fmt" "time" ) 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 处理一次。
[root@bogon test]# go run limiting.go
request 1 2023-03-24 13:31:21.749198759 +0800 CST m=+0.201225820
request 2 2023-03-24 13:31:21.948369603 +0800 CST m=+0.400396672
request 3 2023-03-24 13:31:22.148223808 +0800 CST m=+0.600250870
request 4 2023-03-24 13:31:22.348781186 +0800 CST m=+0.800808247
request 5 2023-03-24 13:31:22.548318857 +0800 CST m=+1.000345920
# 第二批请求,我们直接连续处理了 3 次,这是由于这个“脉冲”
# 速率控制,然后大约每 200ms 处理其余的 2 个。
request 1 2023-03-24 13:31:22.548353012 +0800 CST m=+1.000380071
request 2 2023-03-24 13:31:22.548357382 +0800 CST m=+1.000384441
request 3 2023-03-24 13:31:22.548360008 +0800 CST m=+1.000387077
request 4 2023-03-24 13:31:22.748488 +0800 CST m=+1.200515052
request 5 2023-03-24 13:31:22.948772078 +0800 CST m=+1.400799129
[root@bogon test]#
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。