Skip to content

Commit 89fad0f

Browse files
committed
✨ handle concurrency with sync.Map
1 parent d40208e commit 89fad0f

File tree

2 files changed

+33
-9
lines changed

2 files changed

+33
-9
lines changed

README.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,4 +90,31 @@ func (r *RateLimiter) RateLimiterMiddleware(next http.Handler, limit rate.Limit,
9090
next.ServeHTTP(w, req)
9191
})
9292
}
93+
```
94+
95+
## handle concurrency problem with sync.Map
96+
97+
```golang
98+
var ipLimiterMap sync.Map
99+
100+
// RateLimiterMiddleware - 建立 ratelimiter middleware
101+
func (r *RateLimiter) RateLimiterMiddleware(next http.Handler, limit rate.Limit, burst int) http.Handler {
102+
103+
// var mu sync.Mutex
104+
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
105+
// Fetch IP
106+
ip := r.getIP(req)
107+
// Create limiter if not present for IP
108+
limiterAny, _ := ipLimiterMap.LoadOrStore(ip, rate.NewLimiter(limit, burst))
109+
limiter := limiterAny.(*rate.Limiter)
110+
// return error if the limit has been reached
111+
if !limiter.Allow() {
112+
w.Header().Set("Content-Type", "application/json")
113+
w.WriteHeader(http.StatusTooManyRequests)
114+
json.NewEncoder(w).Encode(map[string]string{"error": "Too many requests"})
115+
return
116+
}
117+
next.ServeHTTP(w, req)
118+
})
119+
}
93120
```

internal/service/rate_limiter/rate-limiter.go

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,21 +22,18 @@ func (r *RateLimiter) getIP(req *http.Request) string {
2222
return host
2323
}
2424

25+
var ipLimiterMap sync.Map
26+
2527
// RateLimiterMiddleware - 建立 ratelimiter middleware
2628
func (r *RateLimiter) RateLimiterMiddleware(next http.Handler, limit rate.Limit, burst int) http.Handler {
27-
ipLimiterMap := make(map[string]*rate.Limiter)
28-
var mu sync.Mutex
29+
30+
// var mu sync.Mutex
2931
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
3032
// Fetch IP
3133
ip := r.getIP(req)
3234
// Create limiter if not present for IP
33-
mu.Lock()
34-
limiter, exists := ipLimiterMap[ip]
35-
if !exists {
36-
limiter = rate.NewLimiter(limit, burst)
37-
ipLimiterMap[ip] = limiter
38-
}
39-
mu.Unlock()
35+
limiterAny, _ := ipLimiterMap.LoadOrStore(ip, rate.NewLimiter(limit, burst))
36+
limiter := limiterAny.(*rate.Limiter)
4037
// return error if the limit has been reached
4138
if !limiter.Allow() {
4239
w.Header().Set("Content-Type", "application/json")

0 commit comments

Comments
 (0)