前言
限流器是后台服务中十分重要的组件,在实际的业务场景中使用居多,其设计在网关和一些后台服务中会经常遇到。限流器的作用是用来限制其请求的速率,保护后台响应服务,以免服务过载导致服务不可用现象出现。
**
在 Golang 库中官方给我们提供了限流器的实现 golang.org/x/time/rate
,它是基于令牌桶算法(Token Bucket)设计实现的。
代码实现
编写中间件
// Create a rate limiter with a maximum number of operations to perform per second.
func RateLimitMiddleware() gin.HandlerFunc {
rateCfg := config.GetConfig().Rate
r := rate.Every(time.Duration(rateCfg.Limit) * time.Second)
limit := rate.NewLimiter(r, rateCfg.Burst)
return func(c *gin.Context) {
if !limit.Allow() {
fmt.Println("The current flow is too big, please try again later")
c.JSON(http.StatusOK, gin.H{
"status": status.RequestRateLimit,
"message": status.GetStatusMessage(status.RequestRateLimit),
})
c.Abort()
return
}
}
}
测试接口
// Test controller
middleRateLimit := md.RateLimitMiddleware()
testHandler := testHandler.New()
test := router.Group("/V1/internal/test", middleRateLimit)
{
test.GET("/rate-limit", testHandler.RateLimitTest) // Testing rate limit for request
}
接口返回
// Test an interface that rate limit for request
func (h *handler) RateLimitTest(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"status": 200,
"message": "Success",
})
}
测试用例
Postman
Jmeter
拓展
- uber 开源库中基于漏斗算法实现了一个限流器。漏斗算法可以限制流量的请求速度,并起到削峰的作用。
[https://github.com/uber-go/ratelimit](https://github.com/uber-go/ratelimit)
- 滴滴开源实现了一个对http请求的限流器中间件。可以基于以下模式限流。
- 基于IP,路径,方法,header,授权用户等限流
- 通过自定义方法限流
- 还支持基于 http header 设置限流数据
- 实现方式是基于
github/go/time
实现的,不同类别的数据都存储在一个带超时时间的数据池中。 - 代码地址
[https://github.com/didip/tollbooth](https://github.com/didip/tollbooth)
- golang 网络包中还有基于信号量实现的限流器。
[https://github.com/golang/net/blob/master/netutil/listen.go](https://github.com/golang/net/blob/master/netutil/listen.go)
也值得我们去学习下。