Rate Limiting und Throttling in C#: Anfrageflüsse zähmen

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 C#: So schützen Sie Ihre API vor Überlastungen und bewahren die Nerven Ihrer Benutzer

\n\n

Stellen Sie sich vor: Sie haben eine coole API gestartet. Der Server fliegt, die Datenbank antwortet sofort. Doch plötzlich – peng! – ein unvorsichtiger Client (oder, noch schlimmer, ein DDoS-Angriff) beginnt, Ihren Endpunkt mit tausenden Anfragen pro Sekunde zu bombardieren. Der Server fällt aus, die Datenbank erstickt, und die echten Benutzer sehen einen 503-Fehler. Kommt Ihnen das bekannt vor?

\n\n

Die Lösung für dieses Problem sind Rate Limiting (Geschwindigkeitsbegrenzung) und Throttling (Drosselung). In C# haben wir alle Werkzeuge, um diese Mechanismen elegant und effizient zu implementieren. In diesem Artikel gehen wir nicht nur die Theorie durch – wir schreiben echten Code, analysieren gängige Algorithmen und finden heraus, was für die jeweilige Aufgabe am besten geeignet ist. Schnallen Sie sich an, es wird heiß!

\n\n

Rate Limiting vs Throttling: Was ist der Unterschied?

\n\n

Obwohl diese Begriffe oft verwechselt werden, gibt es eine klare Grenze zwischen ihnen:

\n
    \n
  • Rate Limiting – eine „harte“ Blockierung. Wenn ein Benutzer das Limit überschreitet (z. B. 100 Anfragen pro Minute), gibt der Server HTTP 429 (Too Many Requests) zurück. Die Anfragen erreichen die Geschäftslogik gar nicht erst.
  • \n
  • Throttling – eine „weiche“ Verlangsamung. Der Server nimmt die Anfrage an, verarbeitet sie jedoch mit Verzögerung oder senkt die Priorität. Der Benutzer erhält keinen Fehler, aber seine Arbeitsgeschwindigkeit sinkt.
  • \n
\n

In C# können wir beide Ansätze implementieren und oft für verschiedene Szenarien kombinieren.

\n\n

Rate-Limiting-Algorithmen: Vom Einfachen zum Komplexen

\n\n

Bevor wir Code schreiben, lassen Sie uns die Mathematik verstehen. Es gibt vier „goldene“ Algorithmen, die 90 % der Lösungen zugrunde liegen.

\n\n

1. Fixed Window (Festes Fenster)

\n

Der einfachste Weg. Wir teilen die Zeit in feste Intervalle (z. B. 1 Minute) und zählen die Anfragen in jedem Fenster. Sobald der Zähler das Limit erreicht – blockieren wir.

\n

Vorteile: Einfach zu implementieren. Nachteile: Problem des „Randeffekts“ (Burst beim Übergang zwischen Fenstern).

\n\n
public class FixedWindowRateLimiter\n{\n    private readonly int _limit;\n    private readonly TimeSpan _windowSize;\n    private int _counter;\n    private DateTime _windowStart;\n\n    public FixedWindowRateLimiter(int limit, TimeSpan windowSize)\n    {\n        _limit = limit;\n        _windowSize = windowSize;\n        _windowStart = DateTime.UtcNow;\n    }\n\n    public bool AllowRequest()\n    {\n        var now = DateTime.UtcNow;\n        if (now - _windowStart >= _windowSize)\n        {\n            // Fenster zurücksetzen\n            _counter = 0;\n            _windowStart = now;\n        }\n\n        if (_counter >= _limit)\n            return false; // Too Many Requests\n\n        Interlocked.Increment(ref _counter);\n        return true;\n    }\n}
\n\n

2. Sliding Window (Gleitendes Fenster)

\n

Weiterentwicklung des Fixed Window. Anstelle fester Grenzen berücksichtigen wir Anfragen in einem gleitenden Zeitabschnitt. Üblicherweise durch Protokollierung von Zeitstempeln (z. B. in einem Ringpuffer) implementiert.

\n

Vorteile: Glättet Spitzen. Nachteile: Etwas komplexer in der Implementierung, erfordert Speicher für die Speicherung der Zeitstempel.

\n\n
public class SlidingWindowRateLimiter\n{\n    private readonly int _limit;\n    private readonly TimeSpan _windowSize;\n    private readonly Queue<DateTime> _timestamps = new();\n\n    public SlidingWindowRateLimiter(int limit, TimeSpan windowSize)\n    {\n        _limit = limit;\n        _windowSize = windowSize;\n    }\n\n    public bool AllowRequest()\n    {\n        var now = DateTime.UtcNow;\n        lock (_timestamps)\n        {\n            // Veraltete Zeitstempel entfernen\n            while (_timestamps.Count > 0 && now - _timestamps.Peek() > _windowSize)\n                _timestamps.Dequeue();\n\n            if (_timestamps.Count >= _limit)\n                return false;\n\n            _timestamps.Enqueue(now);\n            return true                

Blogs

Buchempfehlungen