- Go语言入门
- Go语言开发环境安装配置
- Go语言程序结构
- Go语言基础语法
- Go语言数据类型
- Go语言变量
- Go语言常量
- Go语言运算符
- Go语言条件和决策
- Go语言循环
- Go语言函数
- Go语言作用域规则
- Go语言字符串
- Go语言数组
- Go语言指针
- Go语言结构体
- Go语言切片
- Go语言范围(range)
- Go语言映射
- Go语言递归
- Go语言类型转换
- Go语言接口
- Go语言错误处理
-
Go编程代码实例
- Hello World程序实例
- Go变量实例
- Go常量实例
- Go for循环语句实例
- Go if/else语句实例
- Go switch语句实例
- Go切片实例
- Go范围实例
- Go函数实例
- Go函数多个返回值实例
- Go可变参数的函数实例
- Go闭包(匿名函数)实例
- Go函数递归实例
- Go指针实例
- Go指针实例
- Go接口实例
- Go错误实例
- Go程序实例
- Go通道实例
- Go通道缓冲实例
- Go通道同步实例
- Go通道路线实例
- Go Select实例
- Go超时(timeouts)实例
- Go非阻塞通道操作实例
- Go关闭通道实例
- Go通道范围实例
- Go计时器实例
- Go断续器实例
- Go工作池实例
- Go速率限制实例
- Go原子计数器实例
- Go互斥体实例
- Go有状态的goroutines实例
- Go排序实例
- Go按自定义函数排序实例
- Go panic错误处理实例
- Go延迟(defer)实例
- Go集合函数实例
- Go字符串函数实例
- Go字符串格式化实例
- Go正则表达式实例
- Go JSON实例
- Go时间日期实例
- Go时代(Epoch)实例
- Go时间格式化/解析实例
- Go随机数实例
- Go数字解析实例
- Go URL解析实例
- Go SHA1哈希实例
- Go Base64编码实例
- Go读取文件实例
- Go写文件实例
- Go行过滤器实例
- Go命令行参数实例
- Go命令行标志实例
- Go环境变量实例
- Go执行过程实例
- Go信号实例
- Go退出程序实例
Go速率限制实例
速率限制是控制资源利用和维持服务质量的重要机制。通过goroutines
,channel
和ticker
都可以优雅地支持速率限制。
首先我们来看一下基本速率限制。假设想限制对传入请求的处理。我们会在相同名称的通道上放送这些要求。
这个限制器通道将每200
毫秒接收一个值。这是速率限制方案中的调节器。
通过在服务每个请求之前阻塞来自限制器信道的接收,我们限制自己每200
毫秒接收1
个请求。
我们可能希望在速率限制方案中允许短脉冲串请求,同时保持总体速率限制。可以通过缓冲的限制器通道来实现。这个burstyLimiter
通道将允许最多3
个事件的突发。
填充通道以表示允许突发。
每200
毫秒,将尝试向burstyLimiter
添加一个新值,最大限制为3
。现在模拟5
个更多的传入请求。这些传入请求中的前3
个未超过burstyLimiter
值。
运行程序后,就会看到第一批请求每〜200
毫秒处理一次。
对于第二批请求,程序会立即服务前3
个,因为突发速率限制,然后剩余2
服务都具有〜200ms
延迟。
所有的示例代码,都放在
F:\worksp\golang
目录下。安装Go编程环境请参考:/tutorial/detail-5562.html
rate-limiting.go
的完整代码如下所示 -
package main import "time" import "fmt" func main() { // First we'll look at basic rate limiting. Suppose // we want to limit our handling of incoming requests. // We'll serve these requests off a channel of the // same name. requests := make(chan int, 5) for i := 1; i <= 5; i++ { requests <- i } close(requests) // This `limiter` channel will receive a value // every 200 milliseconds. This is the regulator in // our rate limiting scheme. limiter := time.Tick(time.Millisecond * 200) // By blocking on a receive from the `limiter` channel // before serving each request, we limit ourselves to // 1 request every 200 milliseconds. for req := range requests { <-limiter fmt.Println("request", req, time.Now()) } // We may want to allow short bursts of requests in // our rate limiting scheme while preserving the // overall rate limit. We can accomplish this by // buffering our limiter channel. This `burstyLimiter` // channel will allow bursts of up to 3 events. burstyLimiter := make(chan time.Time, 3) // Fill up the channel to represent allowed bursting. for i := 0; i < 3; i++ { burstyLimiter <- time.Now() } // Every 200 milliseconds we'll try to add a new // value to `burstyLimiter`, up to its limit of 3. go func() { for t := range time.Tick(time.Millisecond * 200) { burstyLimiter <- t } }() // Now simulate 5 more incoming requests. The first // 3 of these will benefit from the burst capability // of `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()) } }
执行上面代码,将得到以下输出结果 -
F:\worksp\golang>go run rate-limiting.go request 1 2017-01-21 14:43:39.1445218 +0800 CST request 2 2017-01-21 14:43:39.345767 +0800 CST request 3 2017-01-21 14:43:39.5460635 +0800 CST request 4 2017-01-21 14:43:39.7441739 +0800 CST request 5 2017-01-21 14:43:39.9444929 +0800 CST request 1 2017-01-21 14:43:39.9464898 +0800 CST request 2 2017-01-21 14:43:39.9504928 +0800 CST request 3 2017-01-21 14:43:39.9544955 +0800 CST request 4 2017-01-21 14:43:40.1467214 +0800 CST request 5 2017-01-21 14:43:40.3469624 +0800 CST