diff --git a/config.yaml b/config.yaml index 0dca340..c40d2f3 100644 --- a/config.yaml +++ b/config.yaml @@ -7,7 +7,7 @@ server: logging: - level: info + level: debug # Pretty print for human consumption otherwise json pretty: true # Log incoming requests @@ -25,11 +25,11 @@ rateLimit: # How many requests per ip adress are allowed bucketSize: 50 # How many requests per ip address are refilled - refillSize: 10 + refillSize: 50 # How often requests per ip address are refilled - refillTime: 1m + refillTime: 30s # How often Ip Addresses get cleaned up (only ip addresses with max allowed requests are cleaned up) - cleanupTime: 5m + cleanupTime: 45s hosts: diff --git a/middleware/rate-limit.go b/middleware/rate-limit.go index 18f533c..6589276 100644 --- a/middleware/rate-limit.go +++ b/middleware/rate-limit.go @@ -45,13 +45,13 @@ func (l *Limiter) Manage() { for { select { case ip := <-l.rateChannel: - l.rwLock.Lock() - if counter, ok := l.currentBuckets[ip]; ok { - counter.Add(1) - } else { - counter := &atomic.Int64{} - l.currentBuckets[ip] = counter + if l.AddIfExists(ip) { + break } + + l.rwLock.Lock() + counter := &atomic.Int64{} + l.currentBuckets[ip] = counter l.rwLock.Unlock() case <-l.refillTicker.C: l.rwLock.RLock() @@ -66,6 +66,7 @@ func (l *Limiter) Manage() { l.rwLock.RUnlock() log.Trace().Msg("Refreshed Limits") case <-l.cleanupTicker.C: + start := time.Now() l.rwLock.Lock() deletedBuckets := 0 for ip := range l.currentBuckets { @@ -75,10 +76,22 @@ func (l *Limiter) Manage() { } } l.rwLock.Unlock() - log.Debug().Int("deleted_buckets", deletedBuckets).Msg("Cleaned up Buckets") + duration := time.Since(start) + log.Debug().Str("duration", duration.String()).Int("deleted_buckets", deletedBuckets).Msg("Cleaned up Buckets") } } +} +// Adds one if ip already exists and returns true +// If ip doesnt yet exist only returns false +func (l *Limiter) AddIfExists(ip string) bool { + l.rwLock.RLock() + defer l.rwLock.RUnlock() + if counter, ok := l.currentBuckets[ip]; ok { + counter.Add(1) + return true + } + return false } func (l *Limiter) RateLimiter(next http.Handler) http.Handler { diff --git a/router.go b/router.go index 84ceaf8..4dd0204 100644 --- a/router.go +++ b/router.go @@ -62,7 +62,14 @@ func (router *Router) Healthz(w http.ResponseWriter, r *http.Request) { } healthy := true - res, err := router.client.Get(fmt.Sprintf("http://localhost:%d/healthz", host.Port)) + var url string + if host.Secure { + url = fmt.Sprintf("https://%s:%d/healthz", host.Remote, host.Port) + } else { + url = fmt.Sprintf("http://%s:%d/healthz", host.Remote, host.Port) + } + + res, err := router.client.Get(url) if err != nil { log.Warn().Err(err).Int("port", host.Port).Msg("Unhealthy") healthy = false @@ -89,7 +96,7 @@ func (router *Router) Healthz(w http.ResponseWriter, r *http.Request) { } func (router *Router) Route(w http.ResponseWriter, r *http.Request) { - port, ok := router.domains.Get(r.Host) + host, ok := router.domains.Get(r.Host) if !ok { log.Warn().Str("host", r.Host).Msg("Could not find Host") w.WriteHeader(http.StatusOK) @@ -102,15 +109,15 @@ func (router *Router) Route(w http.ResponseWriter, r *http.Request) { subUrlPath := r.URL.RequestURI() var url string - if port.Secure { - url = fmt.Sprintf("https://%s:%d%s", port.Remote, port.Port, subUrlPath) + if host.Secure { + url = fmt.Sprintf("https://%s:%d%s", host.Remote, host.Port, subUrlPath) } else { - url = fmt.Sprintf("http://%s:%d%s", port.Remote, port.Port, subUrlPath) + url = fmt.Sprintf("http://%s:%d%s", host.Remote, host.Port, subUrlPath) } req, err := http.NewRequest(r.Method, url, r.Body) if err != nil { - log.Error().Err(err).Str("remote", port.Remote).Str("path", subUrlPath).Int("port", port.Port).Msg("Could not create request") + log.Error().Err(err).Bool("secure", host.Secure).Str("remote", host.Remote).Str("path", subUrlPath).Int("port", host.Port).Msg("Could not create request") w.WriteHeader(http.StatusInternalServerError) return } @@ -132,7 +139,7 @@ func (router *Router) Route(w http.ResponseWriter, r *http.Request) { res, err := router.client.Do(req) if err != nil { - log.Error().Err(err).Str("remote", port.Remote).Str("path", subUrlPath).Int("port", port.Port).Msg("Could not complete request") + log.Error().Err(err).Str("remote", host.Remote).Str("path", subUrlPath).Int("port", host.Port).Msg("Could not complete request") w.WriteHeader(http.StatusInternalServerError) return }