Also laut dem Haproxy-Autor, der ein oder zwei Dinge über http weiß:
Keep-Alive wurde erfunden, 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, während sie von niemandem außer dem Client verwendet werden können, der sie geöffnet hat. 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. Hoch geladene Sites deaktivieren häufig Keep-Alive, um die maximale Anzahl gleichzeitiger Clients zu unterstützen. Der eigentliche Nachteil, wenn Sie nicht am Leben bleiben, ist eine leicht erhöhte Latenz beim Abrufen von Objekten. Browser verdoppeln die Anzahl gleichzeitiger Verbindungen auf nicht Keepalive-Sites, um dies auszugleichen.
(von http://haproxy.1wt.eu/ )
Stimmt dies mit der Erfahrung anderer überein? dh ohne am Leben zu bleiben - ist das Ergebnis jetzt kaum noch spürbar? (Es ist wahrscheinlich erwähnenswert, dass mit Websockets usw. - eine Verbindung unabhängig vom Keep-Alive-Status ohnehin "offen" gehalten wird - für sehr reaktionsschnelle Apps). Ist der Effekt für Personen, die vom Server entfernt sind, größer - 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 stammen).
Gedanken?
(Ich bin mir nicht sicher, ob dies eine Sache von serverfault.com ist, aber ich werde den Beitrag erst überqueren, wenn mir jemand sagt, dass ich ihn dorthin verschieben soll.)
quelle
Antworten:
Hey, da ich der Autor dieses Zitats bin, werde ich antworten :-)
Auf großen Websites gibt es zwei große Probleme: gleichzeitige Verbindungen und Latenz. Die gleichzeitige Verbindung wird durch langsame Clients verursacht, deren Herunterladen einige Zeit in Anspruch nimmt, und durch inaktive Verbindungsstatus. Diese Leerlaufverbindungszustände werden durch die Wiederverwendung der Verbindung zum Abrufen mehrerer Objekte verursacht, die als Keep-Alive bezeichnet wird, was durch die Latenz weiter erhöht wird. Wenn sich der Client sehr nahe am Server befindet, kann er die Verbindung intensiv nutzen und sicherstellen, dass sie fast nie inaktiv ist. Wenn die Sequenz endet, kümmert sich niemand darum, den Kanal schnell zu schließen, und die Verbindung bleibt lange Zeit offen und unbenutzt. Dies 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 oft viel zu viel, um hohe Lasten aufrechtzuerhalten: Wenn Sie 20000 Clients vor sich haben und diese durchschnittlich ein Objekt pro Sekunde abrufen, werden diese 20000 Verbindungen dauerhaft hergestellt. 20000 gleichzeitige Verbindungen auf einem Allzweckserver wie Apache sind riesig, erfordern je nach geladenen Modulen zwischen 32 und 64 GB RAM, und Sie können wahrscheinlich nicht hoffen, selbst durch Hinzufügen von RAM viel höher zu werden. In der Praxis werden bei 20000 Clients möglicherweise sogar 40000 bis 60000 gleichzeitige Verbindungen auf dem Server angezeigt, da Browser versuchen, 2 bis 3 Verbindungen einzurichten, wenn sie viele abzurufende Objekte haben. und Sie können wahrscheinlich nicht hoffen, viel höher zu gehen, selbst wenn Sie RAM hinzufügen. In der Praxis werden bei 20000 Clients möglicherweise sogar 40000 bis 60000 gleichzeitige Verbindungen auf dem Server angezeigt, da Browser versuchen, 2 bis 3 Verbindungen einzurichten, wenn sie viele abzurufende Objekte haben. und Sie können wahrscheinlich nicht hoffen, viel höher zu gehen, selbst wenn Sie RAM hinzufügen. In der Praxis werden bei 20000 Clients möglicherweise sogar 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 sinkt es um einen Faktor, der der durchschnittlichen Zeit zum Herunterladen eines Objekts bis zur Zeit zwischen Objekten entspricht. Wenn Sie zum Herunterladen eines Objekts (eines Miniaturfotos, einer Schaltfläche usw.) 50 ms benötigen und wie oben 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, um neue Verbindungen herzustellen. Bei weit entfernten Clients tritt eine unangenehme Latenz auf. In der Vergangenheit verwendeten Browser große Mengen gleichzeitiger Verbindungen, wenn Keep-Alive deaktiviert war. Ich erinnere mich an Zahlen von 4 auf MSIE und 8 auf 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 Browser den Schutz der Internetinfrastruktur gewährleisten.
Dies bedeutet, dass es mit heutigen Browsern schwieriger ist, die Nicht-Keep-Alive-Dienste so reaktionsschnell zu machen wie die Keep-Alive-Dienste. Einige Browser (z. B. Opera) verwenden Heuristiken, um Pipelinining zu verwenden. Pipelining ist eine effiziente Methode zur Verwendung von Keep-Alive, da es die Latenz nahezu eliminiert, 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 Latenz 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 am Leben erhalten und sie sofort löschen, wenn die Seite vollständig ist. Aber das sehen wir leider nicht.
Aus diesem Grund müssen einige Sites, die Allzweckserver 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 Domainnamen, damit Downloads parallelisiert werden können. Dies ist besonders problematisch auf Websites, die SSL intensiv nutzen, da der Verbindungsaufbau noch höher ist, da es einen zusätzlichen Roundtrip gibt.
Was heutzutage häufiger beobachtet wird, ist, dass solche Sites Light-Frontends wie Haproxy oder Nginx bevorzugen, die problemlos Zehntausende von gleichzeitigen Verbindungen verarbeiten können. Sie ermöglichen es, auf der Clientseite am Leben zu bleiben und sie auf der Clientseite zu deaktivieren 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 bietet dies das Beste aus beiden Welten: geringe Latenz aufgrund von Keep-Alive mit sehr geringen Zeitüberschreitungen auf der Clientseite und geringe 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 der LB befinden, ist der Gewinn nicht viel höher als bei der vorherigen Lösung, erfordert jedoch häufig Anpassungen an der Anwendung, um sicherzustellen, dass aufgrund der unerwarteten gemeinsamen Nutzung einer Verbindung zwischen mehreren Benutzern kein Risiko für Sitzungskreuzungen zwischen Benutzern besteht . Theoretisch sollte dies niemals passieren. Die Realität sieht anders aus :-)
quelle
In den Jahren, seit dies geschrieben wurde (und hier auf stackoverflow gepostet wurde), haben wir jetzt Server wie Nginx, die immer beliebter werden.
nginx kann beispielsweise 10.000 Keep-Alive-Verbindungen in einem einzigen Prozess mit nur 2,5 MB (Megabyte) RAM offen halten. Tatsächlich ist es einfach, mehrere Tausend Verbindungen mit sehr wenig RAM offen zu halten, und die einzigen Grenzen, die Sie treffen, sind andere Grenzen, wie die Anzahl der offenen Dateihandles oder TCP-Verbindungen.
Keep-Alive war ein Problem, nicht wegen eines Problems mit der Keep-Alive-Spezifikation selbst, sondern wegen des prozessbasierten Skalierungsmodells von Apache und wegen 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 den gesamten RAM belegt, den ein PHP-Prozess belegt, auch wenn er vollständig inaktiv ist und nur als Keep-Alive geöffnet bleibt. Dies ist nicht skalierbar. Server müssen jedoch nicht auf diese Weise entworfen werden - es gibt keinen besonderen Grund, warum ein Server jede Keep-Alive-Verbindung in einem separaten Prozess halten muss (insbesondere nicht, wenn jeder dieser Prozesse über einen vollständigen PHP-Interpreter verfügt). PHP-FPM und ein ereignisbasiertes Serververarbeitungsmodell wie das in Nginx lösen das Problem elegant.
Update 2015:
SPDY und HTTP / 2 ersetzen die Keep-Alive-Funktionalität von HTTP durch etwas noch Besseres: Die Möglichkeit, eine Verbindung nicht nur am Leben zu erhalten und mehrere Anforderungen und Antworten darüber zu stellen, sondern sie auch zu multiplexen, sodass die Antworten in beliebiger Reihenfolge gesendet werden können und parallel und nicht nur in der Reihenfolge, in der sie angefordert wurden. Dies verhindert, dass langsame Antworten schnellere blockieren, und beseitigt die Versuchung für Browser, mehrere parallele Verbindungen zu einem einzelnen Server offen zu halten. Diese Technologien unterstreichen weiter die Unzulänglichkeiten des mod_php-Ansatzes und die Vorteile eines ereignisbasierten (oder zumindest multithreaded) Webservers, der separat mit etwas wie PHP-FPM gekoppelt ist.
quelle
Mein Verständnis war, dass es wenig mit der CPU zu tun hatte, sondern mit der Latenz beim Öffnen wiederholter Sockets auf der anderen Seite der Welt. Selbst wenn Sie über eine unendliche Bandbreite verfügen, verlangsamt die Verbindungslatenz den gesamten Prozess. verstärkt, wenn Ihre Seite Dutzende von Objekten enthält. Selbst eine dauerhafte Verbindung hat eine Anforderungs- / Antwortlatenz, die sich jedoch verringert, wenn Sie durchschnittlich über zwei Sockets verfügen. Einer sollte Daten streamen, während der andere blockieren könnte. Außerdem wird ein Router niemals davon ausgehen, dass ein Socket eine Verbindung herstellt, bevor Sie darauf schreiben können. Es braucht den vollen Roundtrip-Handschlag. Auch hier behaupte ich nicht, ein Experte zu sein, aber so habe ich es immer gesehen. Was wirklich cool wäre, ist ein vollständig ASYNC-Protokoll (nein, kein vollständig krankes Protokoll).
quelle
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 als kein CDN sein, selbst wenn Sie vollständig dynamische Inhalte bereitstellen.
Wenn Sie lange am Leben bleiben, sodass jeder PoP grundsätzlich eine permanente Verbindung zu Ihrem Server hat, können Benutzer beim ersten Besuch Ihrer Site einen schnellen TCP-Handshake mit ihrem lokalen PoP durchführen, anstatt einen langsamen Handshake mit Ihnen. (Light selbst benötigt ungefähr 100 ms, um sich über Glasfaser um die halbe Welt zu bewegen. Für den Aufbau einer TCP-Verbindung müssen drei Pakete hin und her übertragen werden. SSL erfordert drei Roundtrips .)
quelle