rate_limit.go 1.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. package middleware
  2. import (
  3. "fmt"
  4. "time"
  5. "gitee.com/xuyiping_admin/pkg/apierr"
  6. "gitee.com/xuyiping_admin/pkg/xerr"
  7. "github.com/gin-gonic/gin"
  8. limit "github.com/yangxikun/gin-limit-by-key"
  9. "golang.org/x/time/rate"
  10. )
  11. // RateLimit limit rate by client ip
  12. // limit 10 qps/client_ip and permit bursts of at most 10 tokens, and the limiter live time duration is 3 minutes
  13. // handle exceed rate limit request
  14. func RateLimit(opts ...*RateLimitOption) gin.HandlerFunc {
  15. var opt *RateLimitOption
  16. if len(opts) == 0 {
  17. opt = defaultRateLimitOption
  18. } else {
  19. opt = opts[0]
  20. }
  21. return limit.NewRateLimiter(func(c *gin.Context) string {
  22. return fmt.Sprintf("%s-%s", c.ClientIP(), authorization(c))
  23. }, func(c *gin.Context) (*rate.Limiter, time.Duration) {
  24. return rate.NewLimiter(rate.Every(opt.Interval), opt.Tokens), opt.LiveTime
  25. }, func(c *gin.Context) {
  26. apierr.AbortBadRequest(c, 429, xerr.Customf("request too many %s", c.ClientIP()))
  27. })
  28. }
  29. type RateLimitOption struct {
  30. Interval time.Duration
  31. Tokens int
  32. LiveTime time.Duration
  33. }
  34. var defaultRateLimitOption = &RateLimitOption{
  35. Interval: 100 * time.Millisecond,
  36. Tokens: 10,
  37. LiveTime: 3 * time.Minute,
  38. }
  39. var testRateLimitOption = &RateLimitOption{
  40. Interval: 10 * time.Millisecond,
  41. Tokens: 1000,
  42. LiveTime: 1 * time.Minute,
  43. }
  44. func RateLimitOptionLow() *RateLimitOption {
  45. return &RateLimitOption{
  46. Interval: 1 * time.Second,
  47. Tokens: 10,
  48. LiveTime: 3 * time.Minute,
  49. }
  50. }