Ratenbegrenzung ist ein entscheidendes Konzept in der Webentwicklung und im API-Design. Es stellt sicher, dass Benutzer oder Systeme innerhalb eines bestimmten Zeitraums nur eine begrenzte Anzahl von Anfragen an einen Server stellen können. In diesem Blogbeitrag werden wir untersuchen, was Ratenbegrenzung ist, warum sie wichtig ist und wie man eine einfache Ratenbegrenzung in Go implementiert.
Stellen Sie sich einen Themenpark mit einer Achterbahnfahrt vor, in der alle 10 Minuten nur 10 Personen Platz finden. Wenn mehr als 10 Personen versuchen, innerhalb dieses Zeitraums weiterzukommen, müssen sie warten. Diese Analogie spiegelt das Prinzip der Ratenbegrenzung in Softwaresystemen wider.
Technisch gesehen begrenzt die Ratenbegrenzung die Anzahl der Anfragen, die ein Client (z. B. ein Benutzer, ein Gerät oder eine IP-Adresse) innerhalb eines vordefinierten Zeitraums an einen Server senden kann. Es hilft:
Zum Beispiel könnte eine API 100 Anfragen pro Minute und Benutzer zulassen. Wenn ein Benutzer dieses Limit überschreitet, lehnt der Server weitere Anfragen ab, bis das Limit zurückgesetzt wird.
Eine gängige Methode zur Implementierung einer Ratenbegrenzung ist der Token-Bucket-Algorithmus. So funktioniert es:
Lassen Sie uns einen Ratenbegrenzer in Go erstellen, der jeden Client auf 3 Anfragen pro Minute begrenzt.
Wir verwenden den sync.Mutex, um die Thread-Sicherheit zu gewährleisten und Informationen wie die Anzahl der Token, die maximale Kapazität und die Nachfüllrate zu speichern.
package main import ( "sync" "time" ) type RateLimiter struct { tokens float64 // Current number of tokens maxTokens float64 // Maximum tokens allowed refillRate float64 // Tokens added per second lastRefillTime time.Time // Last time tokens were refilled mutex sync.Mutex } func NewRateLimiter(maxTokens, refillRate float64) *RateLimiter { return &RateLimiter{ tokens: maxTokens, maxTokens: maxTokens, refillRate: refillRate, lastRefillTime: time.Now(), } }
Tokens sollten regelmäßig basierend auf der seit der letzten Auffüllung verstrichenen Zeit aufgefüllt werden.
func (r *RateLimiter) refillTokens() { now := time.Now() duration := now.Sub(r.lastRefillTime).Seconds() tokensToAdd := duration * r.refillRate r.tokens += tokensToAdd if r.tokens > r.maxTokens { r.tokens = r.maxTokens } r.lastRefillTime = now }
Die Allow-Methode bestimmt anhand der verfügbaren Token, ob eine Anfrage fortgesetzt werden kann.
func (r *RateLimiter) Allow() bool { r.mutex.Lock() defer r.mutex.Unlock() r.refillTokens() if r.tokens >= 1 { r.tokens-- return true } return false }
Um die Anfragen pro Client zu begrenzen, erstellen wir eine Zuordnung der IP-Adressen zu ihren jeweiligen Ratenbegrenzern.
type IPRateLimiter struct { limiters map[string]*RateLimiter mutex sync.Mutex } func NewIPRateLimiter() *IPRateLimiter { return &IPRateLimiter{ limiters: make(map[string]*RateLimiter), } } func (i *IPRateLimiter) GetLimiter(ip string) *RateLimiter { i.mutex.Lock() defer i.mutex.Unlock() limiter, exists := i.limiters[ip] if !exists { // Allow 3 requests per minute limiter = NewRateLimiter(3, 0.05) i.limiters[ip] = limiter } return limiter }
Zuletzt erstellen wir eine HTTP-Middleware, die das Ratenlimit für jeden Client durchsetzt.
package main import ( "sync" "time" ) type RateLimiter struct { tokens float64 // Current number of tokens maxTokens float64 // Maximum tokens allowed refillRate float64 // Tokens added per second lastRefillTime time.Time // Last time tokens were refilled mutex sync.Mutex } func NewRateLimiter(maxTokens, refillRate float64) *RateLimiter { return &RateLimiter{ tokens: maxTokens, maxTokens: maxTokens, refillRate: refillRate, lastRefillTime: time.Now(), } }
Hier erfahren Sie, wie Sie alles zusammenfügen und den Ratenbegrenzer testen.
func (r *RateLimiter) refillTokens() { now := time.Now() duration := now.Sub(r.lastRefillTime).Seconds() tokensToAdd := duration * r.refillRate r.tokens += tokensToAdd if r.tokens > r.maxTokens { r.tokens = r.maxTokens } r.lastRefillTime = now }
Starten Sie den Server und testen Sie ihn mit Curl oder Ihrem Browser:
func (r *RateLimiter) Allow() bool { r.mutex.Lock() defer r.mutex.Unlock() r.refillTokens() if r.tokens >= 1 { r.tokens-- return true } return false }
GitHub Repo
Das obige ist der detaillierte Inhalt vonRatenbegrenzung für Anfänger: Was es ist und wie man eine solche in Go erstellt. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!