Les proxys inverses HTTP activent-ils généralement HTTP Keep-Alive du côté client de la connexion proxy et non du côté serveur?

30

HAProxy a la possibilité d'activer la persistance HTTP côté client (client <-> HAProxy) mais de le désactiver côté serveur (serveur HAProxy <->).

Certains de nos clients se connectent à notre service Web par satellite, donc la latence est d'environ 600 ms et je pense qu'en activant la persistance, cela accélérera un peu les choses. Ai-je raison?

Est-ce pris en charge par Nginx? Est-ce une fonctionnalité largement implémentée dans d'autres équilibreurs de charge logiciels et matériels? Quoi d'autre que HAProxy?

LostInComputer
la source

Réponses:

43

modifier: Ma réponse ne couvre que la question d'origine non modifiée, qui était de savoir si ce genre de chose est typique des équilibreurs de charge / procurations inverses. Je ne sais pas si nginx / produit X prend en charge cela, 99,9% de mon expérience de proxy inverse est avec HAproxy.

Correct. HTTP Keep-Alive côté client, mais pas côté serveur.

Pourquoi?

Si vous décomposez quelques détails, vous pouvez rapidement voir pourquoi c'est un avantage. Pour cet exemple, supposons que nous chargeons une page www.example.com et que cette page comprend 3 images, img [1-3] .jpg.

Navigateur chargeant une page, sans Keep-Alive

  1. Le client établit une connexion TCP avec www.example.com sur le port 80
  2. Le client effectue une requête HTTP GET pour "/"
  3. Le serveur envoie le contenu HTML de l'URI "/" (qui inclut des balises HTML référençant les 3 images)
  4. Le serveur ferme la connexion TCP
  5. Le client établit une connexion TCP avec www.example.com sur le port 80
  6. Le client effectue une requête HTTP GET pour "/img1.jpg"
  7. Le serveur envoie l'image
  8. Le serveur ferme la connexion TCP
  9. Le client établit une connexion TCP avec www.example.com sur le port 80
  10. Le client effectue une requête HTTP GET pour "/img2.jpg"
  11. Le serveur envoie l'image
  12. Le serveur ferme la connexion TCP
  13. Le client établit une connexion TCP avec www.example.com sur le port 80
  14. Le client effectue une requête HTTP GET pour "/img3.jpg"
  15. Le serveur envoie l'image
  16. Le serveur ferme la connexion TCP

Notez qu'il y a 4 sessions TCP séparées établies puis fermées.

Navigateur chargeant une page, avec Keep-Alive

HTTP Keep-Alive permet à une seule connexion TCP de servir plusieurs requêtes HTTP, l'une après l'autre.

  1. Le client établit une connexion TCP avec www.example.com sur le port 80
  2. Le client effectue une requête HTTP GET pour "/" et demande également au serveur d'en faire une session HTTP Keep-Alive.
  3. Le serveur envoie le contenu HTML de l'URI "/" (qui inclut des balises HTML référençant les 3 images)
  4. Le serveur ne ferme pas la connexion TCP
  5. Le client fait et demande HTTP GET pour "/img1.jpg"
  6. Le serveur envoie l'image
  7. Le client fait et demande HTTP GET pour "/img2.jpg"
  8. Le serveur envoie l'image
  9. Le client fait et demande HTTP GET pour "/img3.jpg"
  10. Le serveur envoie l'image
  11. Le serveur ferme la connexion TCP si aucune autre requête HTTP n'est reçue pendant son délai d'expiration HTTP Keep-Alive

Notez qu'avec Keep-Alive, une seule connexion TCP est établie et finalement fermée.

Pourquoi Keep-Alive mieux?

Pour répondre à cela, vous devez comprendre ce qu'il faut pour établir une connexion TCP entre un client et un serveur. C'est ce que l'on appelle la négociation TCP à 3 voies.

  1. Le client envoie un paquet SYN (chronisé)
  2. Le serveur renvoie un ACK SYN (chronisé) (nowledgement), SYN-ACK
  3. Le client envoie un paquet ACK (nowledgement)
  4. La connexion TCP est désormais considérée comme active par le client et le serveur

Les réseaux ont une latence, donc chaque étape de la prise de contact à 3 voies prend un certain temps. Disons qu'il y a 30 ms entre le client et le serveur, l'envoi aller-retour des paquets IP requis pour établir la connexion TCP signifie qu'il faut 3 x 30 ms = 90 ms pour établir une connexion TCP.

Cela peut ne pas sembler beaucoup, mais si nous considérons que dans notre exemple d'origine, nous devons établir 4 connexions TCP distinctes, cela devient 360 ms. Et si la latence entre le client et le serveur est de 100 ms au lieu de 30 ms? Ensuite, nos 4 connexions mettent 1200 ms à s'établir.

Pire encore, une page Web typique peut nécessiter bien plus que seulement 3 images pour se charger, il peut y avoir plusieurs fichiers CSS, JavaScript, image ou autres que le client doit demander. Si la page charge 30 autres fichiers et que la latence client-serveur est de 100 ms, combien de temps passons-nous à établir des connexions TCP?

  1. Pour établir 1 connexion TCP, il faut 3 x latence, soit 3 x 100 ms = 300 ms.
  2. Nous devons le faire 31 fois, une fois pour la page et 30 fois pour chaque autre fichier référencé par la page. 31 x 300 ms = 9,3 secondes.

9,3 secondes passées à établir des connexions TCP pour charger une page Web qui référence 30 autres fichiers. Et cela ne compte même pas le temps passé à envoyer des requêtes HTTP et à recevoir des réponses.

Avec HTTP Keep-Alive, nous n'avons besoin que d'établir 1 connexion TCP, ce qui prend 300 ms.

Si HTTP Keep-Alive est si génial, pourquoi ne pas l'utiliser également côté serveur?

Les proxys inverses HTTP (comme HAproxy) sont généralement déployés très près des serveurs principaux pour lesquels ils procurent des proxys. Dans la plupart des cas, la latence entre le proxy inverse et ses serveurs principaux sera inférieure à 1 ms, donc l'établissement d'une connexion TCP est beaucoup plus rapide qu'elle ne l'est entre un client.

Mais ce n'est que la moitié de la raison. Un serveur HTTP alloue une certaine quantité de mémoire pour chaque connexion client. Avec Keep-Alive, il maintiendra la connexion vivante et, par extension, conservera une certaine quantité de mémoire en cours d'utilisation sur le serveur, jusqu'à ce que le délai d'expiration Keep-Alive soit atteint, qui peut atteindre 15 secondes, selon la configuration du serveur. .

Donc, si nous considérons les effets de l'utilisation de Keep-Alive du côté serveur d'un proxy inverse HTTP, nous augmentons le besoin de mémoire, mais parce que la latence entre le proxy et le serveur est si faible, nous n'obtenons aucun avantage réel de la réduction du temps nécessaire à la prise de contact à 3 voies de TCP, il est donc généralement préférable de simplement désactiver Keep-Alive entre le proxy et le serveur Web dans ce scénario.

Avertissement: oui, cette explication ne prend pas en compte le fait que les navigateurs établissent généralement plusieurs connexions HTTP à un serveur en parallèle. Cependant, il y a une limite au nombre de connexions parallèles qu'un navigateur établira avec le même hôte, et généralement cela est encore assez petit pour rendre la conservation souhaitable.

ThatGraemeGuy
la source
5
Bravo pour l'excellente explication Graeme, je n'ai jamais passé assez de temps pour une aussi longue réponse à celui qui m'a demandé cela, et je vais certainement garder un lien vers ce post pour servir de réponse très claire maintenant :-)
Willy Tarreau
2
Y aurait-il un avantage pour keepAlive côté serveur si la connexion entre le proxy et le backend était https?
avmohan
"Un serveur HTTP alloue une certaine quantité de mémoire pour chaque connexion client" oui, mais il y aura peu de ces connexions (?) Une seule par équilibreur de charge? Pas un par client sur Internet (?)
Raedwald
@Raedwald, si votre équilibreur de charge se limite à établir une seule connexion HTTP avec chaque serveur sauvegardé, vous allez avoir un très mauvais moment. :-)
ThatGraemeGuy
7

Nginx prend en charge le maintien en vie des deux côtés.

VBart
la source
Diriez-vous que le maintien en vie est utile pour les backends, s'il y avait une latence entre le proxy et les backends? De plus, qu'est-ce qui permettrait un nombre optimal de connexions en vie?
CMCDragonkai
@CMCDragonkai Si vos backends sont situés sur des serveurs dédiés, il peut être utile d'éviter la latence de connexion qui dépend de votre réseau. Il n'y a pas de moyenne d'or, le nombre optimal dépend principalement de votre configuration, de votre environnement, de votre application et du modèle de demande.
VBart
J'espère trouver une équation pour résoudre ce problème!
CMCDragonkai
2
La question, telle que je l'ai lue, n'est pas de savoir si nginx prend en charge la persistance en amont, mais si nginx prend en charge la désactivation de la persistance en amont.
user45793