深入解析Golang中的goroutines、channels与tickers:从基础到高级应用
发表时间: 2024-06-03 20:19
在Golang中,我们可以使用goroutines, channels, tickers轻松的建立一个限流器。
速率限制是控制资源利用和维护服务质量的重要机制。Go 语言通过 goroutines, channels, and tickers优雅地支持速率限制。官网上提供了一个具体示例(
https://gobyexample.com/rate-limiting),代码如下:
package mainimport ( "fmt" "time")func main() { //模拟5个请求 requests := make(chan int, 5) for i := 1; i <= 5; i++ { requests <- i } close(requests) // 创建一个每200毫秒就触发一次的 limiter := time.Tick(200 * time.Millisecond) for req := range requests { // 每200毫秒触发一次 <-limiter fmt.Println("request", req, time.Now()) } // 创建有3个缓冲的channel burstyLimiter := make(chan time.Time, 3) // 向channel中添加3个初始值 for i := 0; i < 3; i++ { burstyLimiter <- time.Now() } // 启动一个新的goroutine向channel添加值 go func() { for t := range time.Tick(200 * time.Millisecond) { burstyLimiter <- t } }() // 模拟5个请求 burstyRequests := make(chan int, 5) for i := 1; i <= 5; i++ { burstyRequests <- i } close(burstyRequests) // 限流器开始执行的3个请求会同时到达,后面会每200毫秒执行一次 for req := range burstyRequests { <-burstyLimiter fmt.Println("burstyRequest", req, time.Now()) }}
上面的代码展示两种限流使用,一种是没有带缓冲的,每200毫秒只能处理一个请求。一种是带缓冲的,最开始的3个请求会立即执行,后续的请求依然会按照每200毫秒执行一次。运行上面的代码得到的输出如下:
request 1 2024-06-03 20:13:12.7117775 +0800 CST m=+0.215562501request 2 2024-06-03 20:13:12.9074885 +0800 CST m=+0.411273501request 3 2024-06-03 20:13:13.1030114 +0800 CST m=+0.606796401request 4 2024-06-03 20:13:13.2986761 +0800 CST m=+0.802461101request 5 2024-06-03 20:13:13.5114099 +0800 CST m=+1.015194901burstyRequest 1 2024-06-03 20:13:13.5114099 +0800 CST m=+1.015194901burstyRequest 2 2024-06-03 20:13:13.5114099 +0800 CST m=+1.015194901burstyRequest 3 2024-06-03 20:13:13.5114099 +0800 CST m=+1.015194901burstyRequest 4 2024-06-03 20:13:13.7224927 +0800 CST m=+1.226277701burstyRequest 5 2024-06-03 20:13:13.9186188 +0800 CST m=+1.422403801
从输出的日志中我们刚刚说法得到了验证。request的5个请求时每200毫秒执行一次,burstyRequest的前3个是同时执行,后面两个是按照200毫秒一次执行的 。