Rate Limiting und Throttling in Go: Vollständiger Leitfaden mit Beispielen

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Rate Limiting und Throttling in Go: So schützen Sie Ihre API und behalten den Überblick

\n\n

Stellen Sie sich vor: Sie haben die perfekte API in Go geschrieben. Sie ist blitzschnell, verarbeitet Anfragen in Millisekunden, und dann – peng! – bricht eine Flut von Anfragen auf Ihren Server herein. Vielleicht ein Bot, vielleicht ein Bug im Client, oder einfach nur der Hype um Ihr Produkt. Ohne Schutz bricht der Server zusammen, die Nutzer gehen verloren, und Sie sitzen bis zum Morgen über den Logs.

\n\n

Kommt Ihnen das bekannt vor? Dann sind Rate Limiting (Geschwindigkeitsbegrenzung) und Throttling (Drosselung) Ihre neuen besten Freunde. In diesem Artikel auf pythonlib.ru schauen wir uns an, wie man sie in Go implementiert – einer Sprache, die für hochlastige Systeme entwickelt wurde. Kein Blabla, nur echter Code und reale Anwendungsfälle.

\n\n

Rate Limiting vs. Throttling: Was ist der Unterschied?

\n\n

Lassen Sie uns zunächst die Begriffe klären. Viele verwechseln diese Konzepte, aber es gibt einen Unterschied.

\n\n
    \n
  • Rate Limiting ist eine harte Begrenzung: „Nicht mehr als 100 Anfragen pro Minute“. Wird das Limit überschritten, antwortet der Server mit 429 Too Many Requests. Ganz klar und streng.
  • \n
  • Throttling ist eine weiche Regulierung: „Wir bremsen dich, aber blockieren dich nicht“. Anstatt auf alle Anfragen sofort zu antworten, stellen wir sie in eine Warteschlange und verarbeiten sie mit einer festgelegten Geschwindigkeit.
  • \n
\n\n

In Go lassen sich beide Ansätze dank Goroutinen und Channels elegant umsetzen. Schauen wir uns konkrete Beispiele an.

\n\n

Einfachster Rate Limiter mit Channels

\n\n

Die grundlegendste Methode zur Geschwindigkeitsbegrenzung ist die Verwendung eines Tickers aus dem Paket time. Es ist wie ein Metronom: Jeder „Tick“ erlaubt eine Anfrage.

\n\n
package main\n\nimport (\n    "fmt"\n    "time"\n)\n\nfunc main() {\n    // Erstellen eines Channels, der alle 200 ms Tokens sendet\n    limiter := time.Tick(200 * time.Millisecond)\n\n    // Simulieren von 10 Anfragen\n    for i := 1; i <= 10; i++ {\n        <-limiter // Auf Erlaubnis warten\n        fmt.Printf("Anfrage %d verarbeitet um %s\\n", i, time.Now().Format("15:04:05.000"))\n    }\n}
\n\n

Was passiert hier? time.Tick erstellt einen Channel, der alle 200 Millisekunden einen Wert sendet. Unsere Goroutine blockiert bei <-limiter, bis sie ein Token erhält. Das Ergebnis: exakt 5 Anfragen pro Sekunde, ohne Ausnahmen.

\n\n

Nachteil: Wenn es weniger Anfragen als Ticks gibt, warten wir einfach. Ineffizient? Ja. Aber für einfache Szenarien ideal.

\n\n

Burst-Limiting mit Puffer

\n\n

Was aber, wenn wir Verkehrsspitzen durchlassen müssen? Zum Beispiel 10 Anfragen sofort erlauben und dann auf 5 pro Sekunde begrenzen. Dafür verwenden wir einen gepufferten Channel – den klassischen Token Bucket.

\n\n
package main\n\nimport (\n    "fmt"\n    "time"\n)\n\nfunc main() {\n    // Gepufferter Channel für 5 Tokens\n    tokens := make(chan struct{}, 5)\n\n    // Befüller-Goroutine: fügt alle 200 ms ein Token hinzu\n    go func() {\n        ticker := time.NewTicker(200 * time.Millisecond)\n        defer ticker.Stop()\n        for range ticker.C {\n            select {\n            case tokens <- struct{}{}:\n            default:\n                // Channel ist voll – nichts tun\n            }\n        }\n    }()\n\n    // Simulation von 15 Anfragen\n    for i := 1; i <= 15; i++ {\n        <-tokens // Token nehmen (warten, wenn leer)\n        fmt.Printf("Anfrage %d verarbeitet um %s\\n", i, time.Now().Format("15:04:05.000"))\n        time.Sleep(50 * time.Millisecond) // Kleine Verzögerung zwischen Anfragen\n    }\n}
\n\n

Die ersten 5 Anfragen werden sofort durchgelassen (Puffer ist voll), danach eine alle 200 ms. Dieses Muster ist ideal für APIs, bei denen ein Client plötzlich viele Anfragen senden kann (z. B. nach einem Neustart).

\n\n

Throttling mit WaitGroup und Worker Pool

\n\n

Kommen wir nun zum Throttling. Angenommen, wir haben eine Aufgabenwarteschlange (z. B. E-Mail-Newsletter versenden). Wir wollen den Client nicht blockieren, aber auch die

Blogs

Buchempfehlungen