赞
踩
middleware/rateLimiterMiddleware.go
package middleware import ( "net/http" "time" "github.com/gin-gonic/gin" "golang.org/x/time/rate" ) var Limiter *rate.Limiter // 定义一个中间件函数来进行限流 func RateLimiterMiddleware() gin.HandlerFunc { return func(c *gin.Context) { if !Limiter.AllowN(time.Now(), 1) { c.JSON(http.StatusTooManyRequests, gin.H{"message": "Rate limit exceeded"}) // 设置休眠和业务时长一样,为了更好从日志出看出规则 time.Sleep(50 * time.Millisecond) c.Abort() return } c.Next() } }
main.go
func main() { r := gin.Default() // 创建一个限流器,每秒允许最多10个请求 middleware.Limiter = rate.NewLimiter(rate.Limit(10), 1) // 使用限流中间件 r.Use(middleware.RateLimiterMiddleware()) r.GET("/api/resource", func(c *gin.Context) { time.Sleep(50 * time.Millisecond) c.JSON(http.StatusOK, gin.H{"message": "Resource accessed"}) }) r.Run(":8080") }
使用ab压力测试,并发量为1的(相当于串行),在1秒内不断发出请求(算下来,每个请求50ms,总共能发出20个请求)
middleware/ipRateLimiterMiddleware.go
package middleware import ( "net/http" "sync" "time" "github.com/gin-gonic/gin" "golang.org/x/time/rate" ) var IPLimiter *IPRateLimiter func NewIPRateLimiter() *IPRateLimiter { return &IPRateLimiter{ limiter: make(map[string]*rate.Limiter), } } type IPRateLimiter struct { mu sync.Mutex limiter map[string]*rate.Limiter } func (i *IPRateLimiter) GetLimiter(ip string) *rate.Limiter { i.mu.Lock() defer i.mu.Unlock() limiter, exists := i.limiter[ip] if !exists { limiter = rate.NewLimiter(2, 5) // 每秒2个请求,桶容量为5 i.limiter[ip] = limiter } return limiter } // 定义一个中间件函数来进行限流 func IPRateLimiterMiddleware() gin.HandlerFunc { return func(c *gin.Context) { ip := c.ClientIP() limiter := IPLimiter.GetLimiter(ip) if !limiter.Allow() { c.JSON(http.StatusTooManyRequests, gin.H{"message": "Rate limit exceeded"}) // 设置休眠和业务时长一样,为了更好从日志出看出规则 time.Sleep(50 * time.Millisecond) c.Abort() return } c.Next() } }
main.go
func main() { r := gin.Default() // 创建IP限流器 middleware.IPLimiter = middleware.NewIPRateLimiter() // 使用限流中间件 r.Use(middleware.IPRateLimiterMiddleware()) r.GET("/api/resource", func(c *gin.Context) { time.Sleep(50 * time.Millisecond) c.JSON(http.StatusOK, gin.H{"message": "Resource accessed"}) }) r.Run(":8080") }
使用ab压力测试,并发量为1的(相当于串行),在1秒内不断发出请求(算下来,每个请求50ms,总共能发出20个请求)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。