Gin 系列讲座: Saas系统, Gin+Jwt+casbin RestFul Api 后端一战到底 5: RateLimit 访问限速

2,218 阅读1分钟

Gin 系列讲座: Saas系统, Gin+Jwt+casbin RestFul Api 后端一战到底 5: RateLimit 访问限速

限速中间件

前面到文章介绍了,gin框架如何加中间件。 还画了个草图。 描述未拨洋葱。。 就是在http request 和下一个处理之间加上一个层

为什么限速

客户端访问 ,很多种情况需要限速。 比如秒杀,高峰期, 防止恶意访问。 还有需要限速购买访问等等很多中情况。都需要限速

如何限速

利用gin 中间件。 如下代码。 可有采用redis 缓存,或者其他替代方案。 来限制 科幻请求的频率。 超过我们设定的频率,则不错了。就是这么简单。


// RateLimiterMiddleware 请求频率限制中间件
func RateLimiterMiddleware(skipper ...SkipperFunc) gin.HandlerFunc {
	cfg := config.GetGlobalConfig().RateLimiter
	if !cfg.Enable {
		return func(c *gin.Context) {
			c.Next()
		}
	}

	rc := config.GetGlobalConfig().Redis
	ring := redis.NewRing(&redis.RingOptions{
		Addrs: map[string]string{
			"server1": rc.Addr,
		},
		Password: rc.Password,
		DB:       cfg.RedisDB,
	})

	limiter := redis_rate.NewLimiter(ring)
	limiter.Fallback = rate.NewLimiter(rate.Inf, 0)

	return func(c *gin.Context) {
		if (len(skipper) > 0 && skipper[0](c)) || limiter == nil {
			c.Next()
			return
		}

		userID := ginplus.GetUserID(c)
		if userID == "" {
			c.Next()
			return
		}

		limit := cfg.Count
		rate, delay, allowed := limiter.AllowMinute(userID, limit)
		if !allowed {
			h := c.Writer.Header()
			h.Set("X-RateLimit-Limit", strconv.FormatInt(limit, 10))
			h.Set("X-RateLimit-Remaining", strconv.FormatInt(limit-rate, 10))
			delaySec := int64(delay / time.Second)
			h.Set("X-RateLimit-Delay", strconv.FormatInt(delaySec, 10))
			ginplus.ResError(c, errors.ErrTooManyRequests)
			return
		}

		c.Next()
	}
}

一个小问题, 我们还有什么功能能加到中间件上去呢?

大家可有想想。自己想的,理解的才是真的学到到。