Skip to content

Commit d1a8c79

Browse files
committed
perf: optimize limiter middleware
1 parent 5482759 commit d1a8c79

2 files changed

Lines changed: 58 additions & 28 deletions

File tree

web/fiber/middleware/limiter.go

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,25 @@ const (
1717
XRateLimitReset = "X-RateLimit-Reset"
1818
)
1919

20-
// DefaultLimitMessage 触发限制时的 429 消息
21-
var DefaultLimitMessage = "处理中的请求数过多"
20+
var (
21+
// DefaultLimitMessage 触发限制时的 429 消息
22+
DefaultLimitMessage = "处理中的请求数过多"
23+
24+
// DefaultLimitReached 达到限制时执行的 Hook
25+
DefaultLimitReached = func(c *fiber.Ctx) error {
26+
return response.APIException(c, http.StatusTooManyRequests, DefaultLimitMessage, nil)
27+
}
28+
)
2229

2330
// RequestsLimiter 同时处理的请求数限制
2431
// 请求处理中 +1, 请求已返回: -1
2532
// 请求超限返回 429 错误
2633
type RequestsLimiter struct {
27-
count atomic.Uint64
2834
limit atomic.Int32
2935
running atomic.Int32
36+
limited atomic.Uint64
3037

31-
// 达到限制时的响应错误消息
32-
msg string
38+
limitReached fiber.Handler
3339
}
3440

3541
func (r *RequestsLimiter) Allow() bool {
@@ -43,14 +49,22 @@ func (r *RequestsLimiter) Allow() bool {
4349
return false
4450
}
4551
if r.running.CompareAndSwap(n, n+1) {
46-
r.count.Add(1)
4752
return true
4853
}
4954
}
5055
}
5156

52-
func (r *RequestsLimiter) Count() uint64 {
53-
return r.count.Load()
57+
func (r *RequestsLimiter) Stats() map[string]int {
58+
return map[string]int{
59+
"Limit": int(r.Limit()),
60+
"Limited": int(r.Limited()),
61+
"Running": int(r.Running()),
62+
"Remaining": int(r.Remaining()),
63+
}
64+
}
65+
66+
func (r *RequestsLimiter) Limited() uint64 {
67+
return r.limited.Load()
5468
}
5569

5670
func (r *RequestsLimiter) SetLimit(n int32) {
@@ -76,7 +90,8 @@ func (r *RequestsLimiter) Remaining() int32 {
7690
func (r *RequestsLimiter) Handler() fiber.Handler {
7791
return func(c *fiber.Ctx) error {
7892
if !r.Allow() {
79-
return response.APIException(c, http.StatusTooManyRequests, r.msg, nil)
93+
r.limited.Add(1)
94+
return r.limitReached(c)
8095
}
8196

8297
defer r.running.Add(-1)
@@ -89,15 +104,15 @@ func (r *RequestsLimiter) Handler() fiber.Handler {
89104
// NewDefaultRequestsLimiter 使用配置文件参数创建限制器
90105
// app.Use(middleware.NewDefaultRequestsLimiter().Handler())
91106
func NewDefaultRequestsLimiter() *RequestsLimiter {
92-
return NewRequestsLimiter(config.Config().WebConf.RequestsLimit, DefaultLimitMessage)
107+
return NewRequestsLimiter(config.Config().WebConf.RequestsLimit, DefaultLimitReached)
93108
}
94109

95-
func NewRequestsLimiter(limit int32, msg string) *RequestsLimiter {
96-
if msg == "" {
97-
msg = DefaultLimitMessage
110+
func NewRequestsLimiter(limit int32, limitReached fiber.Handler) *RequestsLimiter {
111+
if limitReached == nil {
112+
limitReached = DefaultLimitReached
98113
}
99114
r := &RequestsLimiter{
100-
msg: msg,
115+
limitReached: limitReached,
101116
}
102117
r.limit.Store(limit)
103118
return r

web/gin/middleware/limiter.go

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,25 @@ const (
1717
XRateLimitReset = "X-RateLimit-Reset"
1818
)
1919

20-
// DefaultLimitMessage 触发限制时的 429 消息
21-
var DefaultLimitMessage = "处理中的请求数过多"
20+
var (
21+
// DefaultLimitMessage 触发限制时的 429 消息
22+
DefaultLimitMessage = "处理中的请求数过多"
23+
24+
// DefaultLimitReached 达到限制时执行的 Hook
25+
DefaultLimitReached = func(c *gin.Context) {
26+
response.APIException(c, http.StatusTooManyRequests, DefaultLimitMessage, nil)
27+
}
28+
)
2229

2330
// RequestsLimiter 同时处理的请求数限制
2431
// 请求处理中 +1, 请求已返回: -1
2532
// 请求超限返回 429 错误
2633
type RequestsLimiter struct {
27-
count atomic.Uint64
2834
limit atomic.Int32
2935
running atomic.Int32
36+
limited atomic.Uint64
3037

31-
// 达到限制时的响应错误消息
32-
msg string
38+
limitReached gin.HandlerFunc
3339
}
3440

3541
func (r *RequestsLimiter) Allow() bool {
@@ -43,14 +49,22 @@ func (r *RequestsLimiter) Allow() bool {
4349
return false
4450
}
4551
if r.running.CompareAndSwap(n, n+1) {
46-
r.count.Add(1)
4752
return true
4853
}
4954
}
5055
}
5156

52-
func (r *RequestsLimiter) Count() uint64 {
53-
return r.count.Load()
57+
func (r *RequestsLimiter) Stats() map[string]int {
58+
return map[string]int{
59+
"Limit": int(r.Limit()),
60+
"Limited": int(r.Limited()),
61+
"Running": int(r.Running()),
62+
"Remaining": int(r.Remaining()),
63+
}
64+
}
65+
66+
func (r *RequestsLimiter) Limited() uint64 {
67+
return r.limited.Load()
5468
}
5569

5670
func (r *RequestsLimiter) SetLimit(n int32) {
@@ -76,7 +90,8 @@ func (r *RequestsLimiter) Remaining() int32 {
7690
func (r *RequestsLimiter) Handler() gin.HandlerFunc {
7791
return func(c *gin.Context) {
7892
if !r.Allow() {
79-
response.APIException(c, http.StatusTooManyRequests, r.msg, nil)
93+
r.limited.Add(1)
94+
r.limitReached(c)
8095
return
8196
}
8297

@@ -90,15 +105,15 @@ func (r *RequestsLimiter) Handler() gin.HandlerFunc {
90105
// NewDefaultRequestsLimiter 使用配置文件参数创建限制器
91106
// app.Use(middleware.NewDefaultRequestsLimiter().Handler())
92107
func NewDefaultRequestsLimiter() *RequestsLimiter {
93-
return NewRequestsLimiter(config.Config().WebConf.RequestsLimit, DefaultLimitMessage)
108+
return NewRequestsLimiter(config.Config().WebConf.RequestsLimit, DefaultLimitReached)
94109
}
95110

96-
func NewRequestsLimiter(limit int32, msg string) *RequestsLimiter {
97-
if msg == "" {
98-
msg = DefaultLimitMessage
111+
func NewRequestsLimiter(limit int32, limitReached gin.HandlerFunc) *RequestsLimiter {
112+
if limitReached == nil {
113+
limitReached = DefaultLimitReached
99114
}
100115
r := &RequestsLimiter{
101-
msg: msg,
116+
limitReached: limitReached,
102117
}
103118
r.limit.Store(limit)
104119
return r

0 commit comments

Comments
 (0)