92 votes

http keep-alive dans l'ère moderne

Donc, selon l'auteur de haproxy, qui s'y connaît en http :

Le "Keep-alive" a été inventé pour réduire l'utilisation du CPU sur les serveurs lorsque les CPU étaient 100 fois plus lents. Mais ce qui n'est pas dit est que les connexions persistantes consomment beaucoup beaucoup de mémoire alors qu'elles ne sont pas utilisables par personne d'autre que le client qui qui les a ouvertes. Aujourd'hui, en 2009, les processeurs sont très bon marché et la mémoire est toujours limitée à quelques gigaoctets par l'architecture ou le prix. Si un site a besoin de keep-alive, il y a un vrai problème. Les sites très chargés désactivent souvent keep-alive pour supporter le nombre maximum nombre maximal de clients simultanés. Le site réel inconvénient de ne pas avoir de keep-alive est une légère augmentation de la latence pour récupérer des objets. Les navigateurs doublent le nombre de connexions simultanées sur les simultanées sur les sites non-keepalive pour compenser cela.

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

Est-ce que cela correspond à l'expérience d'autres personnes ? c'est-à-dire sans keep-alive - le résultat est-il à peine perceptible maintenant ? (il est probablement utile de noter qu'avec les websockets, etc., une connexion est maintenue "ouverte" indépendamment de l'état du keep-alive, pour les applications très réactives). L'effet est-il plus important pour les personnes qui sont éloignées du serveur - ou s'il y a beaucoup d'artefacts à charger depuis le même hôte lors du chargement d'une page ? (Je pense que des éléments comme les CSS, les images et les JS proviennent de plus en plus de CDN compatibles avec les caches).

Qu'en pensez-vous ?

(je ne sais pas si c'est un problème lié à serverfault.com, mais je ne posterai pas de message croisé avant que quelqu'un me dise de le déplacer là-bas).

140voto

Willy Tarreau Points 1945

Hé, puisque je suis l'auteur de cette citation, je vais répondre :-)

Deux grands problèmes se posent sur les grands sites : les connexions simultanées et la latence. Les connexions simultanées sont causées par des clients lents qui mettent du temps à télécharger le contenu, et par des états de connexion inactifs. Ces états d'inactivité sont dus à la réutilisation de la connexion pour récupérer de multiples objets, ce que l'on appelle le "keep-alive", qui est encore accru par la latence. Lorsque le client est très proche du serveur, il peut faire un usage intensif de la connexion et faire en sorte qu'elle ne soit presque jamais inactive. Cependant, lorsque la séquence se termine, personne ne se soucie de fermer rapidement le canal et la connexion reste ouverte et inutilisée pendant un long moment. C'est la raison pour laquelle de nombreuses personnes suggèrent d'utiliser un délai d'attente keep-alive très bas. Sur certains serveurs comme Apache, le délai d'attente le plus bas que vous pouvez définir est d'une seconde, et c'est souvent beaucoup trop pour supporter des charges élevées : si vous avez 20000 clients en face de vous et qu'ils vont chercher en moyenne un objet par seconde, vous aurez ces 20000 connexions établies en permanence. 20000 connexions simultanées sur un serveur généraliste comme Apache, c'est énorme, cela nécessitera entre 32 et 64 Go de RAM en fonction des modules chargés, et vous ne pouvez probablement pas espérer aller beaucoup plus haut même en ajoutant de la RAM. En pratique, pour 20000 clients, vous pouvez même voir 40000 à 60000 connexions simultanées sur le serveur car les navigateurs essaieront d'établir 2 à 3 connexions s'ils ont beaucoup d'objets à récupérer.

Si vous fermez la connexion après chaque objet, le nombre de connexions simultanées diminuera considérablement. En effet, il diminuera d'un facteur correspondant au temps moyen de téléchargement d'un objet par le temps entre les objets. Si vous avez besoin de 50 ms pour télécharger un objet (une photo miniature, un bouton, etc...), et que vous téléchargez en moyenne 1 objet par seconde comme ci-dessus, alors vous n'aurez que 0,05 connexion par client, soit seulement 1000 connexions simultanées pour 20000 clients.

C'est maintenant que le temps d'établir de nouvelles connexions va compter. Les clients éloignés vont subir une latence désagréable. Dans le passé, les navigateurs utilisaient un grand nombre de connexions simultanées lorsque la fonction "keep-alive" était désactivée. Je me souviens de chiffres de 4 sur MSIE et de 8 sur Netscape. Cela aurait vraiment divisé d'autant la latence moyenne par objet. Maintenant que le keep-alive est présent partout, nous ne voyons plus de chiffres aussi élevés, car cela augmente encore la charge sur les serveurs distants, et les navigateurs se chargent de protéger l'infrastructure d'Internet.

Cela signifie qu'avec les navigateurs d'aujourd'hui, il est plus difficile d'obtenir que les services non-keep-alive soient aussi réactifs que les services keep-alive. En outre, certains navigateurs (par exemple Opera) utilisent des heuristiques pour essayer d'utiliser le pipelinining. Le pipelining est un moyen efficace d'utiliser le keep-alive, car il élimine presque toute latence en envoyant plusieurs requêtes sans attendre de réponse. Je l'ai essayé sur une page contenant 100 petites photos, et le premier accès est environ deux fois plus rapide que sans keep-alive, mais l'accès suivant est environ 8 fois plus rapide, car les réponses sont si petites que seule la latence compte (seulement les réponses "304").

Je dirais que l'idéal serait d'avoir des tunables dans les navigateurs pour qu'ils gardent les connexions en vie entre les objets récupérés, et les suppriment immédiatement lorsque la page est terminée. Mais ce n'est malheureusement pas le cas.

Pour cette raison, certains sites qui doivent installer des serveurs à usage général tels qu'Apache en amont et qui doivent prendre en charge un grand nombre de clients doivent généralement désactiver la fonction "keep-alive". Et pour forcer les navigateurs à augmenter le nombre de connexions, ils utilisent plusieurs noms de domaine afin de pouvoir paralléliser les téléchargements. C'est particulièrement problématique sur les sites faisant un usage intensif du SSL, car le nombre de connexions est encore plus élevé puisqu'il y a un aller-retour supplémentaire.

Ce que l'on observe le plus souvent aujourd'hui, c'est que ces sites préfèrent installer des frontends légers tels que haproxy ou nginx, qui n'ont aucun problème à gérer des dizaines ou des centaines de milliers de connexions simultanées, ils activent le keep-alive du côté client, et le désactivent du côté Apache. De ce côté, le coût d'établissement d'une connexion est presque nul en termes de CPU, et pas du tout perceptible en termes de temps. De cette façon, on obtient le meilleur des deux mondes : faible latence due au keep-alive avec des délais d'attente très bas du côté client, et faible nombre de connexions du côté serveur. Tout le monde est content :-)

Certains produits commerciaux améliorent encore cet aspect en réutilisant les connexions entre l'équilibreur de charge frontal et le serveur et en multiplexant toutes les connexions des clients sur celles-ci. Lorsque les serveurs sont proches du LB, le gain n'est pas beaucoup plus élevé que la solution précédente, mais il faudra souvent adapter l'application pour s'assurer qu'il n'y a pas de risque de croisement de session entre les utilisateurs en raison du partage inattendu d'une connexion entre plusieurs utilisateurs. En théorie, cela ne devrait jamais arriver. La réalité est bien différente :-)

22voto

thomasrutter Points 42905

Depuis que cet article a été écrit (et posté ici sur stackoverflow), nous avons maintenant des serveurs tels que nginx qui gagnent en popularité.

nginx, par exemple, peut maintenir ouvertes 10 000 connexions keep-alive dans un seul processus avec seulement 2,5 Mo (mégaoctets) de RAM. En fait, il est facile de maintenir ouvertes plusieurs milliers de connexions avec très peu de RAM, et les seules limites que vous rencontrerez seront d'autres limites telles que le nombre de handles de fichiers ouverts ou de connexions TCP.

Le problème de la fonction "keep-alive" n'était pas dû à un quelconque problème avec la spécification "keep-alive" elle-même, mais au modèle de mise à l'échelle basé sur les processus d'Apache et à la présence de "keep-alives" sur un serveur dont l'architecture n'était pas conçue pour les accueillir.

Apache Prefork + mod_php + keep-alives est particulièrement problématique. Il s'agit d'un modèle dans lequel chaque connexion continue d'occuper toute la mémoire vive d'un processus PHP, même s'il est complètement inactif et ne reste ouvert qu'en tant que keep-alive. Ce n'est pas évolutif. Mais les serveurs n'ont pas à être conçus de cette façon - il n'y a aucune raison particulière pour qu'un serveur ait besoin de garder chaque connexion keep-alive dans un processus séparé (surtout pas quand chacun de ces processus possède un interpréteur PHP complet). PHP-FPM et un modèle de traitement du serveur basé sur les événements, comme celui de nginx, résolvent le problème de manière élégante.

2voto

catchpolenet Points 11

J'ai cru comprendre que cela n'avait pas grand chose à voir avec le CPU, mais plutôt avec la latence d'ouverture des sockets répétés à l'autre bout du monde. Même si vous avez une bande passante infinie, la latence de connexion ralentira l'ensemble du processus. Elle est amplifiée si votre page comporte des dizaines d'objets. Même une connexion persistante a une latence de demande/réponse, mais elle est réduite lorsque vous avez 2 sockets, car en moyenne, l'un devrait diffuser des données en continu tandis que l'autre pourrait bloquer. De plus, un routeur ne va jamais supposer qu'un socket se connecte avant de vous laisser y écrire. Encore une fois, je ne prétends pas être un expert, mais c'est ainsi que je l'ai toujours vu. Ce qui serait vraiment cool, c'est un protocole entièrement ASYNC (non, pas un protocole entièrement malade).

2voto

mjs Points 9378

Les keep-alives très longs peuvent être utiles si vous utilisez un CDN "origin pull" tel que CloudFront ou CloudFlare. En fait, cela peut s'avérer plus rapide que l'absence de CDN, même si vous servez un contenu entièrement dynamique.

Si vous disposez de longues durées de vie de sorte que chaque PoP dispose d'une connexion permanente à votre serveur, la première fois que les utilisateurs visitent votre site, ils peuvent effectuer une poignée de main TCP rapide avec leur PoP local au lieu d'une poignée de main lente avec vous. (La lumière elle-même met environ 100 ms pour parcourir la moitié du globe via la fibre optique, et l'établissement d'une connexion TCP nécessite le passage de trois paquets dans les deux sens. SSL exige trois aller-retour .)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X