Add more documentation, cleanup rate limit code
This commit is contained in:
@@ -7,7 +7,7 @@ server:
|
|||||||
|
|
||||||
|
|
||||||
logging:
|
logging:
|
||||||
level: info
|
level: debug
|
||||||
# Pretty print for human consumption otherwise json
|
# Pretty print for human consumption otherwise json
|
||||||
pretty: true
|
pretty: true
|
||||||
# Log incoming requests
|
# Log incoming requests
|
||||||
@@ -25,11 +25,11 @@ rateLimit:
|
|||||||
# How many requests per ip adress are allowed
|
# How many requests per ip adress are allowed
|
||||||
bucketSize: 50
|
bucketSize: 50
|
||||||
# How many requests per ip address are refilled
|
# How many requests per ip address are refilled
|
||||||
refillSize: 10
|
refillSize: 50
|
||||||
# How often requests per ip address are refilled
|
# 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)
|
# How often Ip Addresses get cleaned up (only ip addresses with max allowed requests are cleaned up)
|
||||||
cleanupTime: 5m
|
cleanupTime: 45s
|
||||||
|
|
||||||
|
|
||||||
hosts:
|
hosts:
|
||||||
|
|||||||
@@ -45,13 +45,13 @@ func (l *Limiter) Manage() {
|
|||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case ip := <-l.rateChannel:
|
case ip := <-l.rateChannel:
|
||||||
l.rwLock.Lock()
|
if l.AddIfExists(ip) {
|
||||||
if counter, ok := l.currentBuckets[ip]; ok {
|
break
|
||||||
counter.Add(1)
|
|
||||||
} else {
|
|
||||||
counter := &atomic.Int64{}
|
|
||||||
l.currentBuckets[ip] = counter
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
l.rwLock.Lock()
|
||||||
|
counter := &atomic.Int64{}
|
||||||
|
l.currentBuckets[ip] = counter
|
||||||
l.rwLock.Unlock()
|
l.rwLock.Unlock()
|
||||||
case <-l.refillTicker.C:
|
case <-l.refillTicker.C:
|
||||||
l.rwLock.RLock()
|
l.rwLock.RLock()
|
||||||
@@ -66,6 +66,7 @@ func (l *Limiter) Manage() {
|
|||||||
l.rwLock.RUnlock()
|
l.rwLock.RUnlock()
|
||||||
log.Trace().Msg("Refreshed Limits")
|
log.Trace().Msg("Refreshed Limits")
|
||||||
case <-l.cleanupTicker.C:
|
case <-l.cleanupTicker.C:
|
||||||
|
start := time.Now()
|
||||||
l.rwLock.Lock()
|
l.rwLock.Lock()
|
||||||
deletedBuckets := 0
|
deletedBuckets := 0
|
||||||
for ip := range l.currentBuckets {
|
for ip := range l.currentBuckets {
|
||||||
@@ -75,10 +76,22 @@ func (l *Limiter) Manage() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
l.rwLock.Unlock()
|
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 {
|
func (l *Limiter) RateLimiter(next http.Handler) http.Handler {
|
||||||
|
|||||||
21
router.go
21
router.go
@@ -62,7 +62,14 @@ func (router *Router) Healthz(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
healthy := true
|
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 {
|
if err != nil {
|
||||||
log.Warn().Err(err).Int("port", host.Port).Msg("Unhealthy")
|
log.Warn().Err(err).Int("port", host.Port).Msg("Unhealthy")
|
||||||
healthy = false
|
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) {
|
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 {
|
if !ok {
|
||||||
log.Warn().Str("host", r.Host).Msg("Could not find Host")
|
log.Warn().Str("host", r.Host).Msg("Could not find Host")
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
@@ -102,15 +109,15 @@ func (router *Router) Route(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
subUrlPath := r.URL.RequestURI()
|
subUrlPath := r.URL.RequestURI()
|
||||||
var url string
|
var url string
|
||||||
if port.Secure {
|
if host.Secure {
|
||||||
url = fmt.Sprintf("https://%s:%d%s", port.Remote, port.Port, subUrlPath)
|
url = fmt.Sprintf("https://%s:%d%s", host.Remote, host.Port, subUrlPath)
|
||||||
} else {
|
} 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)
|
req, err := http.NewRequest(r.Method, url, r.Body)
|
||||||
if err != nil {
|
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)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -132,7 +139,7 @@ func (router *Router) Route(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
res, err := router.client.Do(req)
|
res, err := router.client.Do(req)
|
||||||
if err != nil {
|
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)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user