从实现上看,limiter 并不是每隔一段时间更新当前桶中令牌的数量,而是记录了上次访问时间和当前桶中令牌的数量。当再次访问时,通过上次访问时间计算出当前桶中的令牌的数量,决定是否可以发放令牌。
使用
下面我们通过一个简单的例子,学习上面介绍的限流器的使用。
limiter := rate.NewLimiter(rate.Every(100*time.Millisecond), 10)
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
if limiter.Allow() {// do something
log.Println("say hello")
}
})
_ = http.ListenAndServe(":13100", nil)
上面,每100 ms 放入令牌桶中1个令牌,所以当批量访问该接口时,可以看到如下结果:
2020/06/26 14:34:16 say hello 有18 条记录
2020/06/26 14:34:17 say hello 有10 条记录
2020/06/26 14:34:18 say hello 有10 条记录
...
一开始漏斗满着,可以缓解部分突发的流量。当漏斗未空时,访问的频次和令牌放入的频次变为一致。
其他限流器的实现
uber 开源库中基于漏斗算法实现了一个限流器。漏斗算法可以限制流量的请求速度,并起到削峰填谷的作用。 https://github.com/uber-go/ratelimit
滴滴开源实现了一个对http请求的限流器中间件。可以基于以下模式限流。
基于IP,路径,方法,header,授权用户等限流 通过自定义方法限流 还支持基于 http header 设置限流数据 实现方式是基于 github/go/time 实现的,不同类别的数据都存储在一个带超时时间的数据池中。 代码地址 https://www.easck.com/d/file/200628/55320200628120009golang 网络包中还有基于信号量实现的限流器。 https://www.easck.com/d/file/200628/57120200628120011.go 也值得我们去学习下。
总结
令牌桶实现的限流器算法,相较于漏斗算法可以在一定程度上允许突发的流量进入我们的应用中,所以在web应用中最为广泛。
在实际使用时,一般不会做全局的限流,而是针对某些特征去做精细化的限流。例如:通过header、x-forward-for 等限制爬虫的访问,通过对 ip,session 等用户信息限制单个用户的访问等。
到此这篇关于Golang 限流器的使用和实现示例的文章就介绍到这了,更多相关Golang 限流器内容请搜索易采站长站以前的文章或继续浏览下面的相关文章希望大家以后多多支持易采站长站!










