it-swarm.com.de

http Keep-Alive in der Moderne

Also nach dem Haproxy-Autor, der ein oder zwei Dinge über http weiß:

Keep-Alive wurde entwickelt, um die CPU-Auslastung auf Servern zu reduzieren, wenn die CPUs 100-mal langsamer waren. Was jedoch nicht gesagt wird, ist, dass dauerhafte Verbindungen viel Speicher verbrauchen und von niemandem außer dem Client, der sie geöffnet hat, verwendet werden können. Heute, im Jahr 2009, sind CPUs sehr billig und der Speicher ist aufgrund der Architektur oder des Preises immer noch auf einige Gigabyte begrenzt. Wenn eine Site am Leben bleiben muss, gibt es ein echtes Problem. Hochgeladene Sites deaktivieren häufig die Keep-Alive-Funktion, um die maximale Anzahl gleichzeitiger Clients zu unterstützen. Der eigentliche Nachteil eines nicht am Leben gehaltenen Geräts ist eine geringfügig erhöhte Latenz beim Abrufen von Objekten. Um dies auszugleichen, verdoppeln Browser die Anzahl gleichzeitiger Verbindungen auf Websites ohne Keepalive-Funktion.

(von http://haproxy.1wt.eu/ )

Stimmt das mit den Erfahrungen anderer überein? also ohne keep-alive - ist das ergebnis jetzt kaum spürbar? (Es ist wahrscheinlich erwähnenswert, dass bei Websockets usw. - für sehr reaktionsschnelle Apps - eine Verbindung ohnehin unabhängig vom Keep-Alive-Status "offen" gehalten wird.) Ist der Effekt für Leute größer, die vom Server entfernt sind - oder wenn beim Laden einer Seite viele Artefakte vom selben Host geladen werden müssen? (Ich würde denken, dass Dinge wie CSS, Bilder und JS zunehmend von cachefreundlichen CDNs kommen).

Gedanken?

(Ich bin mir nicht sicher, ob dies eine Sache von serverfault.com ist, aber ich werde den Post erst dann überqueren, wenn mich jemand auffordert, ihn dorthin zu verschieben).

92
Michael Neale

Hey, da ich der Autor dieses Zitats bin, werde ich antworten :-)

Bei großen Sites gibt es zwei große Probleme: gleichzeitige Verbindungen und Latenz. Gleichzeitige Verbindungen werden durch langsame Clients, bei denen das Herunterladen von Inhalten einige Zeit in Anspruch nimmt, und durch inaktive Verbindungszustände verursacht. Diese Verbindungszustände im Leerlauf werden durch die Wiederverwendung der Verbindung verursacht, um mehrere Objekte abzurufen. Dies wird als Keep-Alive bezeichnet und wird durch die Latenz weiter erhöht. Wenn sich der Client sehr nahe am Server befindet, kann er die Verbindung intensiv nutzen und sicherstellen, dass sie so gut wie nie inaktiv ist. Wenn die Sequenz jedoch endet, kümmert sich niemand darum, den Kanal schnell zu schließen, und die Verbindung bleibt für eine lange Zeit offen und unbenutzt. Das ist der Grund, warum viele Leute vorschlagen, ein sehr geringes Keep-Alive-Timeout zu verwenden. Auf einigen Servern wie Apache beträgt das niedrigste Zeitlimit, das Sie festlegen können, eine Sekunde, und es ist häufig viel zu viel, um hohe Lasten auszuhalten: Wenn Sie 20000 Clients vor sich haben, die durchschnittlich ein Objekt pro Sekunde abrufen, werden Sie habe diese 20000 verbindungen permanent aufgebaut. 20000 gleichzeitige Verbindungen auf einem Allzweck-Server wie Apache sind riesig, erfordern zwischen 32 und 64 GB RAM je nachdem, welche Module geladen sind, und Sie können wahrscheinlich nicht hoffen, dass Sie sogar durch viel höher gehen Hinzufügen von RAM: In der Praxis werden auf 20000 Clients möglicherweise 40000 bis 60000 gleichzeitige Verbindungen auf dem Server angezeigt, da Browser versuchen, 2 bis 3 Verbindungen einzurichten, wenn sie viele abzurufende Objekte haben.

Wenn Sie die Verbindung nach jedem Objekt schließen, sinkt die Anzahl der gleichzeitigen Verbindungen drastisch. In der Tat wird es um einen Faktor fallen, der der durchschnittlichen Zeit zum Herunterladen eines Objekts um die Zeit zwischen Objekten entspricht. Wenn Sie zum Herunterladen eines Objekts (eines Miniaturfotos, einer Schaltfläche usw.) 50 ms benötigen und wie oben beschrieben durchschnittlich 1 Objekt pro Sekunde herunterladen, haben Sie nur 0,05 Verbindungen pro Client, was nur 1000 entspricht gleichzeitige Verbindungen für 20000 Clients.

Jetzt zählt die Zeit, neue Verbindungen aufzubauen. Bei fernen Clients tritt eine unangenehme Latenz auf. In der Vergangenheit verwendeten Browser große Mengen von gleichzeitigen Verbindungen, wenn Keep-Alive deaktiviert war. Ich erinnere mich an Zahlen von 4 bei MSIE und 8 bei Netscape. Dies hätte die durchschnittliche Latenz pro Objekt wirklich durch so viel geteilt. Jetzt, da Keep-Alive überall vorhanden ist, sehen wir keine so hohen Zahlen mehr, da dies die Belastung der Remote-Server weiter erhöht und die Browser die Infrastruktur des Internets schützen.

Dies bedeutet, dass es mit heutigen Browsern schwieriger ist, die nicht am Leben erhaltenden Dienste so reaktionsschnell wie die am Leben erhaltenden Dienste zu machen. Einige Browser (z. B. Opera) verwenden Heuristiken, um Pipelinining zu verwenden. Pipelining ist eine effiziente Möglichkeit, Keep-Alive zu verwenden, da es die Latenz beinahe beseitigt, indem mehrere Anforderungen gesendet werden, ohne auf eine Antwort zu warten. Ich habe es auf einer Seite mit 100 kleinen Fotos versucht, und der erste Zugriff ist ungefähr doppelt so schnell wie ohne Keep-Alive, aber der nächste Zugriff ist ungefähr achtmal so schnell, da die Antworten so klein sind, dass nur die Latenzzeit zählt (nur "304" Antworten).

Ich würde sagen, dass wir im Idealfall einige Tunables in den Browsern haben sollten, damit sie die Verbindungen zwischen abgerufenen Objekten aufrechterhalten und sie sofort löschen, wenn die Seite vollständig ist. Das sehen wir aber leider nicht.

Aus diesem Grund müssen einige Sites, die Allzweck-Server wie Apache auf der Vorderseite installieren müssen und die eine große Anzahl von Clients unterstützen müssen, im Allgemeinen die Keep-Alive-Funktion deaktivieren. Um Browser zu zwingen, die Anzahl der Verbindungen zu erhöhen, verwenden sie mehrere Domänennamen, damit Downloads parallelisiert werden können. Dies ist besonders problematisch bei Sites, die SSL intensiv nutzen, da der Verbindungsaufbau mit einem zusätzlichen Roundtrip noch höher ist.

Was heutzutage häufiger zu beobachten ist, ist, dass solche Sites Light-Frontends wie Haproxy oder Nginx bevorzugen, die problemlos Zehntausende von gleichzeitigen Verbindungen handhaben können. Sie aktivieren das Keep-Alive auf der Clientseite und deaktivieren es auf der Apache Seite. Auf dieser Seite sind die Kosten für den Verbindungsaufbau in Bezug auf die CPU nahezu Null und in Bezug auf die Zeit überhaupt nicht spürbar. Auf diese Weise wird das Beste aus beiden Welten erzielt: Geringe Latenz aufgrund von Keep-Alive mit sehr geringen Timeouts auf der Clientseite und geringer Anzahl von Verbindungen auf der Serverseite. Alle sind glücklich :-)

Einige kommerzielle Produkte verbessern dies weiter, indem sie Verbindungen zwischen dem Frontload-Balancer und dem Server wiederverwenden und alle Client-Verbindungen über diese multiplexen. Wenn sich die Server in der Nähe des LB befinden, ist der Gewinn nicht viel höher als bei der vorherigen Lösung. Es sind jedoch häufig Anpassungen an der Anwendung erforderlich, um sicherzustellen, dass aufgrund der unerwarteten gemeinsamen Nutzung einer Verbindung zwischen mehreren Benutzern kein Risiko einer Sitzungskreuzung besteht . Theoretisch sollte dies niemals passieren. Die Realität sieht anders aus :-)

140
Willy Tarreau

In den Jahren, seitdem dies geschrieben (und hier auf stackoverflow gepostet) wurde, haben wir jetzt Server wie Nginx, die immer beliebter werden.

mit nginx können beispielsweise 10.000 Keep-Alive-Verbindungen in einem einzigen Prozess mit nur 2,5 MB (Megabyte) RAM geöffnet werden. Tatsächlich ist es einfach, mehrere Tausend Verbindungen mit sehr wenig RAM offen zu halten, und die einzigen Einschränkungen, die Sie treffen, sind andere Einschränkungen, z. B. die Anzahl offener Datei-Handles oder TCP Verbindungen.

Keep-Alive war kein Problem mit der Keep-Alive-Spezifikation selbst, sondern mit dem prozessbasierten Skalierungsmodell von Apache und mit Keep-Alives, die in einen Server gehackt wurden, dessen Architektur nicht dafür ausgelegt war.

Besonders problematisch ist Apache Prefork + mod_php + keep-alives. Dies ist ein Modell, bei dem jede einzelne Verbindung weiterhin alle RAM= belegt, die ein PHP) - Prozess belegt, auch wenn er vollständig inaktiv ist und nur als offen bleibt Keep-Alive Dies ist nicht skalierbar, aber Server müssen nicht so entworfen werden. Es gibt keinen bestimmten Grund, warum ein Server jede Keep-Alive-Verbindung in einem separaten Prozess halten muss (insbesondere nicht, wenn jeder dieser Prozesse ein volles = hat PHP Interpreter). PHP-FPM und ein ereignisbasiertes Serververarbeitungsmodell wie das in nginx lösen das Problem auf elegante Weise.

pdate 2015:

SPDY und HTTP/2 ersetzen die Keep-Alive-Funktionalität von HTTP durch etwas noch Besseres: Die Möglichkeit, eine Verbindung nicht nur aufrechtzuerhalten und mehrere Anforderungen und Antworten zu übermitteln, sondern diese auch zu multiplexen, sodass die Antworten in beliebiger Reihenfolge gesendet werden können und nicht nur in der Reihenfolge, in der sie angefordert wurden. Dies verhindert, dass langsame Antworten schnellere blockieren, und verhindert, dass Browser versuchen, mehrere parallele Verbindungen zu einem einzelnen Server aufrechtzuerhalten. Diese Technologien heben die Unzulänglichkeiten des mod_php-Ansatzes und die Vorteile eines ereignisbasierten (oder zumindest multithreaded) Webservers hervor, der separat mit PHP-FPM gekoppelt ist.

22
thomasrutter

nach meinem Verständnis hatte dies wenig mit der CPU zu tun, sondern mit der Verzögerung beim Öffnen von wiederholten Sockets auf der anderen Seite der Welt. Selbst wenn Sie eine unendliche Bandbreite haben, wird die Verbindungslatenz den gesamten Prozess verlangsamen. wird verstärkt, wenn Ihre Seite Dutzende von Objekten enthält. Selbst eine persistente Verbindung hat eine Anforderungs-/Antwortverzögerung, die sich jedoch verringert, wenn Sie durchschnittlich 2 Sockets haben. Einer sollte Daten streamen, während der andere blockieren könnte. Außerdem geht ein Router niemals davon aus, dass eine Socket-Verbindung besteht, bevor Sie darauf schreiben können. Es benötigt den vollständigen Hin- und Rücktransfer-Handshake. wieder behaupte ich nicht, ein Experte zu sein, aber so habe ich es immer gesehen. Was wirklich cool wäre, ist ein vollständig asynchrones Protokoll (nein, kein vollständig krankes Protokoll).

2
catchpolenet

Sehr lange Keep-Alives können nützlich sein, wenn Sie ein "Origin Pull" -CDN wie CloudFront oder CloudFlare verwenden. Tatsächlich kann dies schneller sein als kein CDN, selbst wenn Sie vollständig dynamische Inhalte bereitstellen.

Wenn Sie lange am Leben bleiben, sodass jeder PoP im Grunde eine permanente Verbindung zu Ihrem Server hat, können Benutzer beim ersten Besuch Ihrer Site einen schnellen TCP= Handshake mit ihrem lokalen PoP ausführen, anstatt Ein langsamer Handschlag mit Ihnen. (Das Licht selbst benötigt ungefähr 100 ms, um über Glasfaser die halbe Welt zu umrunden. Für den Aufbau einer TCP) -Verbindung müssen drei Pakete hin und her geleitet werden. SSL erfordert drei Roundtrips .)

2
mjs