「Go工具箱」一个兼具单机和集群模式的轻量级限流器:throttled
大家好,我是渔夫子。本号新推出「go工具箱」系列,意在给大家分享使用go语言编写的、实用的、好玩的工具。
今天给大家推荐的工具是一个轻量级的限流器,star:1.2k。该工具实现了对资源的访问速率限制,资源可以是特定的 URL、用户或者任何自定义的形式。比如针对HTTP API接口。该包基于通用信源速率算法(generic cell rate algorithm)实现的。其底层存储是内置了内存存储(memstore)和redis两种存储方式。可以根据具体的使用场景实现单机限流和集群限流。
基本使用
下面代码是实现了一个按请求 path 进行限流的 http 服务,允许同一个 path 每分钟 20 次请求,并支持最多 5 个并发请求的 burst:
package main
import (
"fmt"
"log"
"net/http"
"github.com/throttled/throttled/v2"
"github.com/throttled/throttled/v2/store/memstore"
)
func main() {
// 在 store 中添加 key 的数量限制
store, err := memstore.New(65536)
if err != nil {
log.Fatal(err)
}
// 配置限流规则
quota := throttled.RateQuota{
MaxRate: throttled.PerMin(20),
MaxBurst: 5,
}
rateLimiter, err := throttled.NewGCRARateLimiter(store, quota)
if err != nil {
log.Fatal(err)
}
httpRateLimiter := throttled.HTTPRateLimiter{
RateLimiter: rateLimiter,
// 根据 path 进行限流
VaryBy: &throttled.VaryBy{Path: true},
}
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "hello, world\n")
})
http.ListenAndServe(":8080", httpRateLimiter.RateLimit(handler))
}
多种形式的资源定义
此外,我们也可以通过指定 VaryBy 的方式对资源进行更多的定义。在VaryBy中我们可以通过Cookie、IP、HTTP的请求方法、HEADER头、请求查询参数等来更细粒度的定义资源。例如,若想对请求的来源IP进行访问限制,则可以进行如下配置:
httpRateLimiter := throttled.HTTPRateLimiter{
RateLimiter: rateLimiter,
VaryBy: &throttled.VaryBy{Path:true, RemoteAddr:true}
}
自定义超限处理
资源访问超过限额后,HTTPRateLimiter默认提供了一个处理器是DefaultDeniedHandler。同时我们也可以通过自定义HTTPRateLimiter中的DeniedHandler属性来自定义超限后的输出。如下:
httpRateLimiter := throttled.HTTPRateLimiter{
RateLimiter: rateLimiter,
VaryBy: &throttled.VaryBy{Path:true, RemoteAddr:true}
}
httpRateLimiter.DeniedHandler = http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
http.Error(w, "超过限额了", 429)
}))
集群模式限流
throttled包中内置了memstore和redis存储模式。通过memstore存储限流配额 就是单机版的限流模式。如果想对集群进行统一限流则需要使用redis的存储模式。
实现原理
该包是基于GCRA算法实现的。该算法本质上是根据设置的速率来计算每一个请求的理论达到时间,如果该理论达到时间在最大允许通过的时间窗口之内,则允许该请求通过,否则直接丢弃掉。该算法兼具令牌桶的最大容量特性来适应突增的流量,同时也具有漏桶的匀速消耗的特性。
更多项目详情请查看如下链接 :
开源项目地址:https://github.com/throttled/throttled
参考资料:https://baike.baidu.com/item/通用信元速率算法/2083527
---特别推荐---
特别推荐:一个专注go项目实战、项目中踩坑经验及避坑指南、各种好玩的go工具的公众号,「Go学堂」,专注实用性,非常值得大家关注。点击下方公众号卡片,直接关注。关注送《100个go常见的错误》pdf文档。
相关文章
- 2022-09-24:以下go语言代码输出什么?A:1;B:3;C:13;D:7。 package main import ( “fmt“ “io/ioutil
- Go 爬虫之 HTTP 请求 QuickStart
- .NET 7 AOT 的使用以及 .NET 与 Go 互相调用
- 「Go工具箱」一个对语义化版本进行解析、比较的库:go-version
- 「Go工具箱」推荐一个轻量级、语义化的时间处理库:carbon
- GO语言开篇-Go语言急速入门(基础知识点)| 青训营笔记
- 2023-02-25:请用go语言调用ffmpeg,解码mp4文件并保存为YUV420SP格式文件,YUV420P不要转换成YUV420SP。
- Go-包管理-go get(二)
- Go-包管理-go build(一)
- go语言圣经-声明,变量,赋值,类型,包和文件习题详解编程语言
- Go-连接Redis-学习go-redis包详解编程语言
- 环境Go 编译 在 Linux 环境中的体验(go编译linux)
- 深度探索Go语言与Redis结合(go-redis)
- 如何在 Ubuntu 安装 Go 语言编写的 Git 服务器 Gogs
- Go 语言在极小硬件上的运用(二)
- SQL Server快速上手GO!(sqlserver go)
- 使用Go语言实现Redis数据库(用go实现redis)
- 请求简单而快速用Go编写的Redis请求测试(用go写的redis)
- Go语句让Oracle数据库管理更方便(oracle go语句)