Softwarearchitektur verstehen und entscheiden

Aaron KreisÜber mich
Ausfallsicherheit

Rate Limiting

Anzahl der Anfragen je Zeitraum begrenzen

Die Idee und ihr Nutzen

Eine Versicherung bietet Partnerfirmen wie Werkstätten und Gutachterbüros eine Schnittstelle an, über die die Programme der Partnerfirmen den Stand von Schadenfällen abfragen können. Eine solche Schnittstelle legt fest, in welcher Form ein Programm eine Anfrage stellt und in welcher Form es die Antwort erhält: Das Programm einer Werkstatt schickt zum Beispiel die Nummer eines Schadenfalls und erhält den Stand dieses Schadenfalls zurück. Das Programm von Partner A hat einen Fehler und schickt plötzlich mehrere Hundert Anfragen pro Minute. Die Anfragen beantwortet der Schadendienst der Versicherung. Ohne Grenze wäre der Schadendienst so beschäftigt, dass zum Beispiel das Programm von Partner B, einer anderen Partnerfirma, kaum noch Antworten bekommt. Deshalb geht jede Anfrage zuerst an ein eigenes Programm, den Begrenzer. Der Begrenzer lässt von jedem Partner nur 100 Anfragen pro Minute zum Schadendienst durch und weist alle weiteren Anfragen ab. Die Grenze ist so gewählt, dass jeder Partner seine gewöhnliche Arbeit damit erledigen kann, ein fehlerhaftes Programm mit mehreren Hundert Anfragen pro Minute aber gebremst wird. Diese Begrenzung heißt Rate Limiting, auf Deutsch Ratenbegrenzung. Rate meint dabei die Zahl der Anfragen je Zeitraum, hier 100 Anfragen je Minute.

Bausteine: Programm von Partner A: schickt fehlerhaft Hunderte Anfragen; Programm von Partner B: arbeitet normal; Begrenzer: zählt die Anfragen je Partner; Schadendienst: beantwortet Anfragen zum Stand von Schadenfällen. Verbindungen: Programm von Partner A — Begrenzer; Programm von Partner B — Begrenzer; Begrenzer — Schadendienst (höchstens 100 je Partner und Minute). Der Begrenzer lässt von jedem Partner nur 100 Anfragen pro Minute zum Schadendienst durch und weist weitere ab.

Wie funktioniert es?

Der Begrenzer nimmt jede Anfrage entgegen, bevor sie den Schadendienst erreicht. Für jeden Partner führt der Begrenzer einen eigenen Zähler, und die Grenze liegt bei 100 Anfragen je Minute. Das fehlerhafte Programm von Partner A schickt die Anfragen 1 bis 100 mit dem Zugangsschlüssel A, mit dem sich das Programm ausweist. Der Begrenzer erkennt Partner A an diesem Zugangsschlüssel, zählt mit und gibt die Anfragen an den Schadendienst weiter. Der Schadendienst prüft bei jeder Anfrage, ob Partner A angemeldet ist und den Fall sehen darf, und antwortet wie gewohnt. In derselben Minute schickt das Programm von Partner A die Anfrage 101. Der Begrenzer weist Anfrage 101 sofort ab, ohne den Schadendienst zu belasten, und antwortet mit „429: zu viele Anfragen, ab nächster Minute wieder“. Ebenso weist der Begrenzer jede weitere Anfrage von Partner A in dieser Minute ab. Zur selben Zeit schickt das Programm von Partner B eine Anfrage mit dem Zugangsschlüssel B. Partner B hat seinen eigenen Zähler und liegt unter der Grenze. Der Begrenzer gibt die Anfrage von Partner B an den Schadendienst weiter, und Partner B erhält seine Antwort ohne lange Wartezeit. Vom Fehler bei Partner A merkt Partner B nichts.

Die Grenze legt die Versicherung für jeden Partner fest. Der Begrenzer zählt nach einem Merkmal, hier nach dem Zugangsschlüssel. Ein Begrenzer kann ebenso nach dem Nutzer, nach der Partnerfirma oder nach der Netzadresse zählen, von der eine Anfrage kommt. Zählt der Begrenzer nach Netzadresse, teilen sich zum Beispiel alle Mitarbeitenden einer Firma eine gemeinsame Grenze, wenn sie über dieselbe Adresse ins Internet gehen. Welche Anfragen in den Zähler eingehen, hängt vom Zählverfahren ab. Bei einem festen Zeitfenster beginnt zu jeder vollen Minute ein neuer Zähler. Bei einem gleitenden Zeitfenster zählt der Begrenzer immer die Anfragen der letzten 60 Sekunden, von jetzt aus zurückgerechnet. Bei Webschnittstellen ist für die Abweisung der Antwortcode 429 üblich, der „zu viele Anfragen“ bedeutet. Der Begrenzer kann zusätzlich angeben, nach wie vielen Sekunden das aufrufende Programm die Anfrage erneut stellen darf.

Der Begrenzer kann ein eigenes Programm sein oder ein Teil eines Gateways. Ein Gateway ist ein vorgeschaltetes Programm, das alle Anfragen entgegennimmt, bevor sie die eigentlichen Dienste erreichen. Die Begrenzung kann auch im Schadendienst selbst liegen.

Eine abgewiesene Anfrage hat den Schadendienst nie erreicht. Das Programm von Partner A darf deshalb nicht annehmen, dass die Anfrage bearbeitet wurde, und muss die Anfrage nach der genannten Wartezeit erneut stellen, wenn es die Antwort braucht.

Rate Limiting: Partner A wird gebremst, Partner B arbeitet weiter

Beteiligte: Programm von Partner A: schickt fehlerhaft Hunderte Anfragen; Programm von Partner B: arbeitet normal; Begrenzer: 100 Anfragen je Minute, Zähler je Partner; Schadendienst: prüft Anmeldung und Zugriffsrechte. Ablauf: 1. Das Programm von Partner A schickt die Anfragen 1 bis 100 mit dem Zugangsschlüssel A. Der Begrenzer erkennt Partner A an diesem Zugangsschlüssel und zählt mit. 2. Solange Partner A unter der Grenze liegt, gibt der Begrenzer die Anfragen an den Schadendienst weiter. 3. Der Schadendienst prüft bei jeder Anfrage, ob Partner A angemeldet ist und den Fall sehen darf, und antwortet. 4. In derselben Minute schickt das Programm von Partner A die Anfrage 101. 5. Der Begrenzer weist Anfrage 101 ab, ohne den Schadendienst zu belasten, und nennt den Zeitpunkt für den nächsten Versuch. 6. Das Programm von Partner B schickt eine Anfrage. Partner B hat im Begrenzer seinen eigenen Zähler und liegt unter der Grenze. 7. Der Begrenzer gibt die Anfrage von Partner B an den Schadendienst weiter. 8. Der Schadendienst antwortet Partner B ohne lange Wartezeit. Partner B merkt vom Fehler bei Partner A nichts.

Wann ist es sinnvoll und wann nicht?

Rate Limiting lohnt sich

  • Eine Schnittstelle ist aus dem Internet erreichbar. Wer die Schnittstelle absichtlich mit Anfragen überflutet oder massenhaft Daten abgreifen will, erreicht ohne Begrenzung mit jeder Anfrage den Schadendienst. Mit Rate Limiting wird er nach Erreichen der Grenze abgewiesen.
  • Die Server des Schadendienstes können nur eine begrenzte Zahl von Anfragen bearbeiten. Ohne Begrenzung bestimmen die Programme der Partner, wie stark diese Server ausgelastet sind.
  • Mehrere Partner nutzen dieselbe Schnittstelle, und ein einzelner Partner soll die anderen nicht verdrängen können. Ohne Begrenzung belegt jede Anfrage von Partner A Rechenzeit und Datenbankzugriffe beim Schadendienst. Der Schadendienst beschäftigt sich dann fast nur noch mit Partner A, und Partner B muss lange warten oder erhält Fehlermeldungen.
  • Mit den Partnern sind unterschiedliche Nutzungsumfänge vereinbart. Ohne Begrenzung kann jeder Partner mehr Anfragen stellen, als mit ihm vereinbart ist. Das Merkmal, nach dem gezählt wird, und die Höhe der Grenze lassen sich dann an die Verträge und an die tatsächliche Last anpassen. Ein Gutachterbüro mit vielen Aufträgen kann zum Beispiel eine höhere Grenze erhalten als eine kleine Werkstatt.
  • Das Betriebsteam der Versicherung soll erkennen können, bei welchem Partner ein Fehler vorliegt. Ohne Begrenzung sieht das Betriebsteam nur, dass der Schadendienst überlastet ist. Weist der Begrenzer nur Anfragen mit dem Zugangsschlüssel A ab, erkennt das Betriebsteam daran, dass der Fehler im Programm von Partner A liegt.

Rate Limiting ist nicht das Richtige

  • Die Überlastung kommt nicht von einzelnen Partnern mit zu vielen Anfragen, sondern davon, dass viele Partner gleichzeitig arbeiten oder die Datenbank des Schadendienstes langsam antwortet. Feste Grenzen je Partner helfen dann nicht, denn jeder Partner bleibt unter seinen 100 Anfragen, und der Schadendienst ist trotzdem überlastet. Dann richtet das Betriebsteam Throttling ein: Anfragen werden erst gebremst, wenn der Schadendienst tatsächlich stark ausgelastet ist, und sonst gehen alle Anfragen durch. Feste Grenzen je Partner würden dagegen auch Anfragen abweisen, während der Schadendienst noch freie Rechenzeit hat.
  • Der Schadendienst kann schon die gewöhnlichen Anfragen aller Partner nicht bewältigen. Dann startet das Betriebsteam weitere Exemplare desselben Schadendienstes auf zusätzlichen Rechnern, bei Autoscaling auch automatisch je nach Zahl der Anfragen. Ein Lastverteiler, ein Programm, das eingehende Anfragen auf mehrere Exemplare aufteilt, gibt jede Anfrage an eines der Exemplare weiter. Das geht, weil jedes Exemplar jede Anfrage beantworten kann. Eine Grenze oder eine Drosselung würde hier nur Anfragen fehlerfreier Partner abweisen.
  • Die Begrenzung soll die Anmeldung oder die Prüfung der Zugriffsrechte ersetzen. Der Begrenzer zählt nur Anfragen und lässt auch die Anfrage eines Partners nach einem fremden Schadenfall durch, solange der Partner unter seiner Grenze liegt. Deshalb prüft weiterhin der Schadendienst bei jeder Anfrage, ob der Partner angemeldet ist und den Schadenfall sehen darf. So erhält kein Partner Daten zu einem Schadenfall, den er nicht sehen darf.

Nachteile und typische Fehler

Läuft der Begrenzer in mehreren Instanzen, also als mehrere Exemplare desselben Programms nebeneinander, können die Anfragen eines Partners bei jeder dieser Instanzen ankommen. Die Instanzen müssen deshalb einen gemeinsamen Zähler verwenden, etwa in einem gemeinsamen Speicher, der die Zähler im Arbeitsspeicher hält. Ein gemeinsamer Zähler ist allerdings ein zusätzlicher Baustein, der ausfallen kann, und jede Anfrage braucht eine zusätzliche Abfrage dieses Speichers. Fällt der gemeinsame Zähler aus, muss festgelegt sein, ob der Begrenzer dann alle Anfragen durchlässt oder alle abweist. Die Grenzen müssen gepflegt werden: Für jeden Partner muss bekannt sein, wie viele Anfragen er für seine gewöhnliche Arbeit braucht, und bei neuen Verträgen oder wachsender Nutzung müssen die Grenzen angepasst werden. Den Fehler im Programm von Partner A behebt die Begrenzung nicht.

Typische Fehler und woran man sie erkennt:

  • Getrennte Zähler je Instanz: Der Begrenzer läuft in drei Instanzen. Jede Anfrage geht zuerst an einen Lastverteiler, der die eingehenden Anfragen auf die drei Instanzen aufteilt. Der Lastverteiler gibt die Anfragen von Partner A abwechselnd an alle drei Instanzen. Jede Instanz zählt für sich und lässt 100 Anfragen von Partner A je Minute durch. Zusammen erreichen so bis zu 300 Anfragen von Partner A in einer Minute den Schadendienst. Erkennbar ist das an mehr als 100 Anfragen je Minute von Partner A beim Schadendienst, obwohl der Begrenzer Abweisungen meldet.
  • Grenze zu niedrig: Eine zu niedrige Grenze behindert Partner bei ihrer normalen Arbeit. Ein Gutachterbüro mit vielen Aufträgen erhält zur Hauptarbeitszeit regelmäßig die Antwort 429. Erkennbar ist das an Abweisungen bei Partnern, deren Programme fehlerfrei arbeiten, und an Beschwerden über fehlende Antworten.
  • Falsches Merkmal: Der Begrenzer zählt nach Netzadresse statt nach Zugangsschlüssel. Gehen mehrere Werkstätten über denselben Dienstleister ins Internet, teilen sich diese Werkstätten dann eine Grenze und bremsen sich gegenseitig. Erkennbar ist das an Abweisungen für verschiedene Partner, die alle von derselben Netzadresse kommen.
  • Sofortige Wiederholung: Das Programm von Partner A wiederholt jede abgewiesene Anfrage sofort, statt die angegebene Wartezeit abzuwarten. Jede Abweisung löst so sofort die nächste Anfrage aus, und der Begrenzer weist auch diese Anfrage ab. Für jede dieser Anfragen muss der Begrenzer den Zähler von Partner A abfragen und eine Antwort 429 schicken, bis die Minute vorbei ist. Erkennbar ist das an einer sehr hohen Zahl von Antworten 429 an denselben Partner innerhalb weniger Sekunden.

Weiterführend

Verwandte Ansätze

  • API Gateway: gemeinsamer Eingang für alle Anfragen von außen. Der Begrenzer ist häufig ein Teil des API Gateways, das jede Anfrage von außen zuerst annimmt und dann an den zuständigen Dienst weiterleitet.
  • Retry with Backoff: beschreibt, wie ein aufrufendes Programm nach einer Abweisung mit wachsenden Pausen erneut anfragt, statt den Begrenzer sofort wieder zu treffen.
  • Backpressure: Der Empfänger meldet selbst, wie viel er als Nächstes annehmen kann. Rate Limiting setzt dagegen eine feste Grenze, unabhängig davon, wie viel der Dienst gerade schafft.

Quellen

  • IETF: RFC 6585, Additional HTTP Status Codes: legt in Abschnitt 4 den Antwortcode 429 „Too Many Requests“ fest, der eine Angabe zur Wartezeit bis zur nächsten Anfrage enthalten darf, und überlässt dem Server, wie er Aufrufer erkennt und Anfragen zählt.
  • NGINX: Module ngx_http_limit_req_module: Dokumentation eines verbreiteten Webservers, der Anfragen je Merkmal, etwa der Netzadresse des Aufrufers, begrenzt, die Zähler in einem gemeinsamen Speicherbereich hält und den Antwortcode für abgewiesene Anfragen einstellbar macht.