Go语言详解 第8.52节. 请求处理频率控制

频率控制是控制资源利用和保证服务高质量的重要机制。Go可以使用goroutinechannelticker来以优雅的方式支持频率控制。

  1. package main
  2. import "time"
  3. import "fmt"
  4. func main() {
  5. // 首先我们看下基本的频率限制。假设我们得控制请求频率,
  6. // 我们使用一个通道来处理所有的这些请求,这里向requests
  7. // 发送5个数据,然后关闭requests通道
  8. requests := make(chan int, 5)
  9. for i := 1; i <= 5; i++ {
  10. requests <- i
  11. }
  12. close(requests)
  13. // 这个limiter的Ticker每隔200毫秒结束通道阻塞
  14. // 这个limiter就是我们频率控制处理器
  15. limiter := time.Tick(time.Millisecond * 200)
  16. // 通过阻塞从limiter通道接受数据,我们将请求处理控制在每隔200毫秒
  17. // 处理一个请求,注意`<-limiter`的阻塞作用。
  18. for req := range requests {
  19. <-limiter
  20. fmt.Println("request", req, time.Now())
  21. }
  22. // 我们可以保持正常的请求频率限制,但也允许请求短时间内爆发
  23. // 我们可以通过通道缓存来实现,比如下面的这个burstyLimiter
  24. // 就允许同时处理3个事件。
  25. burstyLimiter := make(chan time.Time, 3)
  26. // 填充burstyLimiter,先发送3个数据
  27. for i := 0; i < 3; i++ {
  28. burstyLimiter <- time.Now()
  29. }
  30. // 然后每隔200毫秒再向burstyLimiter发送一个数据,这里是不断地
  31. // 每隔200毫秒向burstyLimiter发送数据
  32. go func() {
  33. for t := range time.Tick(time.Millisecond * 200) {
  34. burstyLimiter <- t
  35. }
  36. }()
  37. // 这里模拟5个请求,burstyRequests的前面3个请求会连续被处理,
  38. // 因为burstyLimiter被先连续发送3个数据的的缘故,而后面两个
  39. // 则每隔200毫秒处理一次
  40. burstyRequests := make(chan int, 5)
  41. for i := 1; i <= 5; i++ {
  42. burstyRequests <- i
  43. }
  44. close(burstyRequests)
  45. for req := range burstyRequests {
  46. <-burstyLimiter
  47. fmt.Println("request", req, time.Now())
  48. }
  49. }

运行结果

  1. request 1 2014-02-21 14:20:05.2696437 +0800 CST
  2. request 2 2014-02-21 14:20:05.4696637 +0800 CST
  3. request 3 2014-02-21 14:20:05.6696837 +0800 CST
  4. request 4 2014-02-21 14:20:05.8697037 +0800 CST
  5. request 5 2014-02-21 14:20:06.0697237 +0800 CST
  6. request 1 2014-02-21 14:20:06.0697237 +0800 CST
  7. request 2 2014-02-21 14:20:06.0697237 +0800 CST
  8. request 3 2014-02-21 14:20:06.0707238 +0800 CST
  9. request 4 2014-02-21 14:20:06.2707438 +0800 CST
  10. request 5 2014-02-21 14:20:06.4707638 +0800 CST

我们从输出的结果上可以看出最后的5个输出结果中,前三个的时间是连续的,而后两个的时间是隔了200毫秒。

本文标签:频率控制 goroutine channel ticker