Alle Beiträge

Reduzierung der Response Time von 2,5 s auf unter eine Sekunde bei 4,2 Mio. Requests

4,2 Millionen Requests in 24 Stunden. Durchschnittlich 774 ms, im Vergleich zu 2,5 Sekunden in der Vorwoche. Hier ist, was sich im Request-Pfad geändert hat, mit echten Perzentilen.

4,2 Millionen Requests in 24 Stunden. Durchschnittliche Response: 774 ms. Erfolgsquote: 99,91 %. Der gleiche Workload lag in den sieben Tagen vor unserem Rebuild bei durchschnittlich 2,5 Sekunden. Das ist ein Rückgang der durchschnittlichen Response Time um 70 %, auf derselben Hardware, gegen dieselben Ziel-Websites, mit demselben Proxy-Pool. Wir haben die Teile des Request-Pfads neu gebaut, die Kunden stillschweigend ihre Abende gekostet haben.

Dies ist ein Bericht darüber, was sich geändert hat, wie die Zahlen tatsächlich aussehen und wo sich Single und Proxy Finder aus gutem Grund unterscheiden.

Zuerst ein Hinweis zu den Daten. Die Zahlen in diesem Post stammen aus Production-Traffic, wobei ein bestimmter Ziel-Host ausgeschlossen wurde. Dieser Host hat die ganze Woche über aktiv Rate Limits angewendet und Requests mit Challenges versehen, und er verfälscht jede Metrik, die du dir ansiehst. Bezieht man ihn ein, sinkt der Erfolg auf etwa 95 %. Aber diese Lücke von 5 % ist kein Versagen unserer Infrastruktur. Es ist eine Website, die Requests ablehnt, unabhängig davon, wie gut unser Picker ist. Wir haben sie herausgenommen, damit du sehen kannst, was das System bei kooperativen Zielen tatsächlich leistet.

Was die Daten zeigen

Hier ist der tägliche Durchschnitt unseres Production-Traffics der letzten Woche:

Tägliche durchschnittliche Response Time im Production-Traffic der letzten 7 Tage, die einen Rückgang von etwa 2,5 Sekunden auf unter 1 Sekunde am 28. April zeigt

22. bis 27. April: Durchschnitte zwischen 2.318 ms und 3.116 ms, Traffic zwischen 2,8 Mio. und 7,7 Mio. Requests pro Tag. Der 25. April sticht mit 3.116 ms bei 7,7 Mio. Requests heraus, was der Samstags-Peak ist (das Wochenend-Volumen ist spürbar höher und treibt den Durchschnitt nach oben). 28. April: 672 ms bei 3,8 Mio. Requests. 29. April (angebrochener Tag, bis 09:00 UTC): Bisher 880 ms bei 1,7 Mio. Requests.

Gleiche Architektur. Gleiche Proxies. Gleiche Ziel-Websites. Anderer Request-Pfad.

Das Bild der Perzentile ist schärfer als der Durchschnitt. Durchschnitte können schlechte Tails verbergen. Perzentile können das nicht.

Latenz-Perzentile vor und nach dem Rebuild: Durchschnitt um 48 Prozent gesenkt, p95 um 54 Prozent, p99 um 61 Prozent

Das Diagramm vergleicht die 24 Stunden nach unserem Rebuild mit den 24 Stunden davor. p50 hat sich kaum bewegt (und stieg um 4 %, das sind ehrliche Daten; der schnelle Pfad war bereits gut und der neue Picker betreibt etwas mehr Aufwand vorab, um am Tail viel einzusparen). Der Durchschnitt sank in diesem Zeitfenster um 48 %. p95 ging von 8,5 Sekunden auf 3,9 Sekunden, eine Reduzierung um 54 %. p99 fiel von 20 Sekunden auf 7,8 Sekunden, eine Senkung um 61 %. Dort sitzt der Schmerz, und das ist es, was du tatsächlich spürst, wenn dein Scraper auf die Rückkehr der langsamsten 5 % der Requests wartet. Verglichen mit den sieben Tagen vor dem Rebuild (wo der Durchschnitt bei etwa 2,5 Sekunden lag), bedeutet der heutige Durchschnitt von 774 ms einen Rückgang von 70 %.

Die Erfolgsquote stieg ebenfalls: von 98,85 % auf 99,91 % im selben Zeitfenster. Speziell bei Proxy Finder erreichte die Quote 99,89 %. Bei Single 99,96 %. Auf diese Zahl sind wir am stolzesten, denn sie sagt dir, wie oft wir beim ersten Versuch nützliche Daten zurückgeben, ohne einen Retry durchführen zu müssen.

Zwei Produkte, zwei Latenz-Profile

Wir vergleichen Single und Proxy Finder nicht miteinander. Sie lösen unterschiedliche Probleme und haben unterschiedliche Latenz-Budgets. Wenn du das eine nutzt und auf die Zahlen des anderen schaust, liest du das falsche Scoreboard.

Latenz-Perzentile für Single und Proxy Finder, die p50, p95 und p99 nebeneinander zeigen

Single ist ein One-Shot HTTP Request durch unsere Infrastruktur. Du gibst uns eine URL und in etwa 99 % der echten Production-Calls eine Proxy-ID, von der du bereits weißt, dass sie funktioniert. Wir rufen die URL über diesen Proxy ab, du erhältst die Response. Keine Rotations-Logik, keine Retry-Kaskade, kein Proxy-Churn. Letzte 24 Stunden: p50 von 100 ms, p95 von 371 ms, p99 von 581 ms. Die meisten Calls sind in unter einer Fünftelsekunde abgeschlossen. Sogar das schlechteste 1 % kommt in unter 600 ms zurück.

Proxy Finder ist der Discovery-Layer. Er rotiert deinen Request über einen Pool von öffentlichen Proxies, validiert jeden Kandidaten, führt bei Fehlschlägen Retries durch und gibt die erste Response zurück, die tatsächlich funktioniert hat, plus die ID des Proxies, der dies getan hat. p50 von 445 ms, p95 von 5,4 Sekunden, p99 von 10,2 Sekunden. Langsamer, weil er es sein muss. Der ganze Sinn besteht darin, dass die IP, mit der dein Scraper die Ziel-Website ansteuert, rotiert und wegwerfbar ist. Du tauschst einige Sekunden Overhead gegen Resilienz gegenüber Blocklists und Rate Limits.

Der Grund, warum Single so schnell ist, ist keine Magie. Es liegt daran, dass Single etwas vertraut, das Proxy Finder erst entdecken musste. Wenn du Proxy Finder einmal aufrufst und er zurückgibt "dieser Proxy hat funktioniert, hier ist seine ID", überspringen nachfolgende Abrufe gegen dasselbe Ziel über Single den gesamten Discovery-Schritt. Du gehst direkt zu dem Proxy, der die Validierung bereits bestanden hat.

Wie Teams sie zusammen nutzen

Die meisten Teams, die ein Ziel häufig ansteuern, folgen einem Zwei-Schritt-Muster. Der erste Call ist explorativ; der Rest ist festgelegt.

Der erste Call geht an Proxy Finder. Er rotiert durch den Pool, validiert jeden Kandidaten gegen deine Accept-Regeln und gibt die Response zusammen mit der ID des Proxies zurück, der funktioniert hat. Diese ID ist dein Handle für jeden zukünftigen Call, der dasselbe Ziel erreichen will.

Jeder Call danach geht an Single, mit angehängter Proxy-ID. Kein Discovery, keine Validierung, keine Retry-Kaskade. Wir leiten deinen Request durch den von dir angegebenen Proxy und streamen die Response zurück. Das ist der Pfad, der bei p50 100 ms erreicht.

Wenn der Proxy, der gestern funktioniert hat, heute blockiert wird, weichst du für einen Call auf Proxy Finder aus, um neu zu entdecken, und setzt dann die Single-Abrufe mit der neuen ID fort. Wir vertuschen keine Veralterung. Wenn eine Proxy-ID, die du uns übergeben hast, tot ist, sagen wir dir schnell Bescheid, damit du rotieren kannst.

Die 99/1-Aufteilung (Single dominiert beim Volumen, Proxy Finder dominiert bei der Discovery) ist der Grund, warum unsere Single-Zahlen so aussehen, wie sie es tun. Es ist nicht so, dass Single von Natur aus ein schnelleres Produkt ist. Es liegt daran, dass Single der Steady State und Proxy Finder der Kalibrierungsschritt ist. Die meisten Workloads sind größtenteils Steady State.

Wenn dein Job lautet "hole dieses JSON von einer sauberen öffentlichen API, der es egal ist, wer anruft", überspringe den Proxy komplett und nutze Single allein. Wenn dein Job lautet "steuere diese geschützte Seite aus einem Pool von Einweg-IPs an, ohne markiert zu werden", kombiniere sie. Sie sind keine Alternativen. Sie sind Phasen desselben Workflows.

Was wir geändert haben

Der Großteil des Gewinns kam durch den Rebuild von drei Dingen im Proxy-Rotations-Pfad. Keine davon waren neue Ideen. Es waren nur Dinge, die wir aufgeschoben hatten.

Der Pool vertraut keinen schlechten Daten mehr. Vor dem Rebuild hat das Proxy-Verzeichnis Einträge länger behalten, als es sollte. Einige dieser Einträge waren nicht mehr erreichbar. Wenn du einen davon ausgewählt hast, bedeutete das, dass du 15 bis 30 Sekunden verbracht hast, um es auf die harte Tour herauszufinden. Wir sind zu einem Modell gewechselt, bei dem der Pool in nahezu Echtzeit widerspiegelt, was tatsächlich aktiv ist, und der Picker IPs bevorzugt, die wir in letzter Zeit erfolgreich gesehen haben.

Quality-Scores pro Proxy, nicht nur up-or-down. Zuvor sah ein Proxy, der 5 Sekunden zum Antworten brauchte, genauso aus wie einer, der 300 ms brauchte, solange beide am Ende erfolgreich waren. Jetzt trackt der Picker auch die Latenz. Langsame-aber-funktionierende Proxies werden in der Queue nach unten gedrückt. Schnelle werden wiederverwendet, solange sie aktuell sind. Das ist wichtiger, als es klingt, denn der Long Tail der Latenz-Verteilung besteht größtenteils aus langsamen-aber-funktionierenden Proxies, die der alte Picker immer wieder ausgewählt hat.

Per-Target Quality-Scores. Ein Proxy, der auf einer Domain zuverlässig ist, kann auf einer anderen unzuverlässig sein. Die IPs, die bei einer Website sauber funktionieren, werden bei einer anderen blockiert oder per Rate Limit eingeschränkt. Unser Picker trackt Erfolg und Latenz jetzt pro Ziel-Host, nicht nur global. Wenn du einen Abruf gegen eine bestimmte Domain anforderst, wählen wir aus den Proxies, die kürzlich auf dieser Domain tatsächlich gut abgeschnitten haben. Global-gute Proxies bleiben im Rennen, aber ein Proxy mit einem starken Track Record auf dem exakten Ziel hat Vorrang vor einem mit einem starken Track Record insgesamt.

Cleverere Retry-Eskalation. Wenn ein Request fehlschlug, haben wir früher sofort parallele Versuche gestartet. Das war verschwenderisch, und schlimmer noch, ein einziger schlechter Proxy konnte eine Kaskade von Folge-Requests auslösen, die wiederum alle fehlschlugen. Jetzt eskalieren Retries sequenziell mit kurzen Backoffs zwischen den Versuchen, sodass ein Fehlschlag ein Fehlschlag und ein Retry ein Retry ist, kein Multiplikator.

Es gibt eine zweite Kategorie von Änderungen, die es wert ist, genannt zu werden, auch wenn sie für dich weniger sichtbar ist.

Restart-Resilienz. Zuvor bedeutete das Redeployen unserer Request-Infrastruktur ein Zeitfenster von 5 bis 15 Minuten, in dem sich die Proxy-Quality-Score-Map von Grund auf neu aufbauen musste. Während dieses Zeitfensters rät der Picker im Grunde genommen. Kunden sahen es als einen Latenz-Spike direkt nach jedem Deploy. Wir persistieren diese Quality-Map nun über Restarts hinweg. Das System fährt warm hoch. Ab heute können wir Infrastruktur-Änderungen mitten am Tag deployen, ohne dir einen Latenz-Spike zu bescheren. Der Restart-Test, den wir heute Morgen durchgeführt haben, zeigte einen Verbindungs-Aussetzer von 15 Sekunden und null Recovery-Zeit danach. Das ist eine leise, aber bedeutsame Änderung in unserer Deploy-Kadenz: Wir müssen Redeploys nicht mehr um deinen Traffic herum planen.

Sauberere Fehler-Signale. Wenn in unserer Infrastruktur etwas schiefgeht, erhält deine Retry-Logik jetzt den richtigen HTTP-Statuscode zum Handeln. Ein Backend, das kurzzeitig nicht verfügbar ist, gibt einen 503 zurück. Ein Backend, das fehlerhaftes JSON zurückgegeben hat, gibt einen 502 zurück. Ein echter interner Fehler gibt einen 500 zurück. Vorher sahen alle drei wie 500er aus, was bedeutete, dass deine Retry-Logik "warten und erneut versuchen" nicht von "das ist kaputt, eskalieren" unterscheiden konnte. Jetzt kann sie es.

Wie das für dich aussieht

Wenn du Scraper gegen rotierte Proxies einsetzt, besteht die praktische Änderung darin, dass deine p95 und p99 im Vergleich zu vor einer Woche jeweils etwa halbiert wurden. Die durchschnittliche Request-Zeit sinkt. Retries aufgrund von langsamen-aber-letztendlich-funktionierenden Proxies sinken. Die Tail-Latenz, die dafür sorgt, dass ein Job mit 1.000 Requests eine Stunde statt 20 Minuten dauert, sinkt damit.

Wenn du Single einsetzt, wirst du sehen, dass sich die Picker-Arbeit hauptsächlich am Tail auszahlt. p99 fiel auf unter 600 ms, was bedeutet, dass selbst deine unglücklichen 1 % der Requests jetzt schnell zurückkommen. Single war bereits schnell. Es ist jetzt konsistent.

Ehrliche Einschränkungen

Wir haben nicht alles behoben. Ein paar Besonderheiten, die weiterhin gelten:

Proxy Finder p99 liegt immer noch bei etwa 10 Sekunden. Wir haben ihn halbiert, aber der Long Tail ist real. Ein Teil davon geht auf unsere Kappe (Pool-Tiefe, Picker-Rauschen bei seltenen Zielen). Vieles davon nicht: Ziel-Websites können von sich aus langsam sein, können Rate Limits auf bestimmte Routen anwenden, Challenge-Seiten ausliefern, deren Prüfung Zeit kostet, oder sie können einfach ins Timeout laufen. Unsere Infrastruktur kann die beste verfügbare IP auswählen, aber sie kann keinen Ziel-Server beschleunigen, der gerade entscheidet, ob er antwortet. Wenn dein Job darauf angewiesen ist, dass jeder Request in unter 5 Sekunden zurückkehrt, setze ein Per-Request-Timeout, das deiner Toleranz entspricht, und vertraue auf den Retry-Layer.

Einige Ziele sind feindselig, und das zeigt sich in deinen Zahlen. Wie oben erwähnt, schließt die Erfolgsquote von 99,91 % einen Host aus, der uns diese Woche aktiv mit Challenges versieht. Ihn einzubeziehen, senkt die Quote auf etwa 95 %. Dieser Host ist kein Einzelfall. Jeder Aggregator, der mit Public-Web-Daten arbeitet, sieht das. Das Ziel verschiebt sich von Woche zu Woche. Der Picker-Rebuild gibt dem System eine viel bessere Chance, um feindselige Ziele herumzurouten, aber er kann eine Website nicht umgehen, die sich entschieden hat, Traffic komplett abzulehnen. Unsere Aufgabe ist es, dir die saubersten Daten für kooperative Fälle zu liefern und bei den feindseligen schnell fehlzuschlagen.

Vergleiche am selben Tag haben ein Rauschen. Das 24-Stunden-Fenster, das wir im Perzentil-Diagramm zeigen, vergleicht den gestrigen Tag mit dem Tag davor. Wochentags-Effekte, Varianz der Ziel-Websites und Pool-Zusammensetzung verschieben sich zwischen zwei beliebigen Zeitfenstern. Wir sind uns der Richtung sicher (das 7-Tage-Diagramm zeigt einen sauberen Wendepunkt am 28. April), aber wenn du uns gegen deinen eigenen Workload benchmarkst, lass den Vergleich über mindestens eine Woche laufen.

Was als Nächstes ansteht

Der Picker-Rewrite ist die Basis. Ein paar Dinge, die wir dahinter eingereiht haben:

Eine gemeinsame Quality-Score-Map über Instanzen hinweg, damit sie voneinander lernen, anstatt unabhängige Maps aufzubauen. Im Moment hat jede ihr eigenes Bild davon, welche Proxies gut sind. Das funktioniert, ist aber verschwenderisch: Jede Instanz zahlt parallel dieselben Lernkosten.

Confidence-basiertes Picking, bei dem wir Proxies bevorzugen, die wir in den letzten Minuten tatsächlich getestet haben, gegenüber solchen, bei denen wir raten. Nützlich für Low-Volume-Kunden, deren Traffic den Picker nicht von allein warmhält.

Und auf längere Sicht: Mehr Entscheidungen in den Picker verlagern, sodass der Per-Target Quality-Score ein Signal unter vielen wird (Ziel-Latenz-Profil, Tageszeit-Muster, Health von Pool-Segmenten). Die Infrastruktur dafür existiert nun, ohne den Hot Path zu verlangsamen.

Der günstigste Request ist derjenige, den wir nicht per Retry wiederholen mussten. Der Picker-Rebuild ist die Wette darauf, dass bessere Daten im Moment der Auswahl mehr Versuche im Nachhinein schlagen. Die Beweise der ersten 24 Stunden zeigen, dass es die richtige Wette ist.