Open Source · MIT

Toll

Ein API-Gateway auf Slim: Schlüssel mit Kontingenten, Token-Bucket, Antwort-Cache und Circuit Breaker — mit einem Trichter, der zeigt, wo jede Anfrage stehen blieb.

v1.0.0 Man sieht, wohin die Anfragen verschwunden sind
Slim 4PHP 8.5PostgreSQL 18PSR-15Tailwind 4
Toll

Ein Anfragezähler erklärt nichts

Gateway-Dashboards zeigen, wie viele Anfragen ankamen. Diese Zahl beantwortet nichts: Sie sagt nicht, ob die Spitze echter Verkehr war oder ein Partner seine eigene 429 in einer Schleife wiederholt hat, ob sich der Cache lohnt, oder warum das Upstream still ist — weil niemand ruft oder weil der Breaker die Tür zuhält.

Toll ist um eine Frage gebaut: wohin sind die Anfragen verschwunden? Jede Stufe der Kette meldet, wie viele sie gestoppt und wie viele sie durchgelassen hat, und die Zahlen gehen von oben nach unten auf: angekommen — minus ohne Schlüssel — minus Kontingent — minus vom Cache bedient — minus Breaker — beim Upstream angekommen.

Was drinsteckt

Sechs Middlewares in fester Reihenfolge

Route, Schlüssel, Kontingent, Cache, Breaker, Proxy. Die Reihenfolge steht in einer Datei und ist das Produkt: Jede Stufe antwortet selbst oder reicht weiter, und die Antwort trägt einen Header mit der Stufe, die sie bedient hat.

Ein Token-Bucket unter Zeilensperre

Auffüllen und Abbuchen geschehen in einem UPDATE ... RETURNING unter Zeilensperre, die Uhr kommt aus der Datenbank statt von einem einzelnen Anwendungsserver. Ein Stoß aus sechzig parallelen Anfragen wird exakt bei der Kapazität gekappt, ohne Doppelbuchung.

Ein Cache nach Anfrage, nicht nach Client

Der Cache-Schlüssel besteht aus Methode, Pfad und sortierter Query — nie aus dem API-Schlüssel, damit eine Antwort alle bedient, die dasselbe fragen. Wer die Version schon hat, bekommt 304 und keinen Body.

Ein Breaker mit einer einzigen Probe

Fällt ein Upstream aus, antwortet das Gateway selbst und sofort mit 503, statt Verbindungen bis zum Timeout zu halten. Genau eine Anfrage wird zur halboffenen Probe — der Übergang ist ein atomares UPDATE, kein Wettlauf.

Perzentile ohne Rohprotokoll

Latenzen landen in einem Histogramm aus neun Körben, minütlich verdichtet und im selben Statement wie die Protokollzeile geschrieben. Die Bildschirme lesen die Verdichtung, p95 über einen Tag kostet bei tausend wie bei einer Million Anfragen gleich viel.

Ehrliche Ablehnungen

Ein fehlerhafter Schlüssel wird an der Form erkannt, bevor er die Datenbank erreicht, ein zu großer Body verlässt das Gateway nie, und jeder Ausgang — auch Ablehnungen — landet im Protokoll und im Trichter. Clients bekommen Retry-After und X-RateLimit-*, kein Schweigen.

Screenshots

Der Trichter: wo jede Anfrage stehen blieb
Der Trichter: wo jede Anfrage stehen blieb
Routen: Cache, Rate, Burst und Body-Größe
Routen: Cache, Rate, Burst und Body-Größe
Schlüssel: Kontingent pro Minute und Tag, Rest im Bucket
Schlüssel: Kontingent pro Minute und Tag, Rest im Bucket
Das Protokoll: Ausgang jeder Anfrage und die Zeit des Upstreams
Das Protokoll: Ausgang jeder Anfrage und die Zeit des Upstreams
Nach Ausgang gefiltert: nur was das Kontingent abgewiesen hat
Nach Ausgang gefiltert: nur was das Kontingent abgewiesen hat
Dunkles Thema
Dunkles Thema

Installation

git clone https://github.com/dripips/toll.git cd toll docker compose up --build

Haben Sie ein Projekt oder eine Idee?

Schreiben Sie mir, dann besprechen wir die Aufgabe.