D'après ce que je comprends, une connexion HTTP pourrait être keep-alive
ou close
.
J'ai envoyé une requête HTTP à un serveur:
GET /page1/ HTTP/1.1
Host: server.com
Connection: keep-alive
Et il a répondu:
HTTP/1.1 200 OK
Connection: keep-alive, close
Essentiellement, je crois que le serveur est buggé car une réponse comme keep-alive, close
c'est ambigu.
Cependant, en tant que récepteur, comment devrions-nous gérer un tel message? Devrions-nous interpréter cette valeur d'en-tête comme keep-alive
ou close
?
TL; DR: Chrome interprète cet en-tête de réponse comme keep-alive
et maintenir une connexion permanente tandis que Firefox ferme chaque connexion.
Je suis tombé sur cette question en essayant d'optimiser le temps de chargement des pages pour mon site Web.
Dans la RFC référencée, je n'ai rien trouvé sur la façon dont plusieurs entrées dans l'en-tête Connection
peuvent être correctement gérées. Il m'a semblé que la mise en œuvre pouvait choisir entre deux possibilités:
close
à l'intérieur, vous pouvez fermer la connexion après la transmissionDonc, je devais le découvrir. Faisons une enquête plus approfondie:
J'ai remarqué que Chrome envoyait toujours une demande HTTP/1.1 avec Connection: keep-alive
et ma configuration par défaut d'Apache répondait toujours par un Connection: close
entête. J'ai donc commencé à enquêter et j'ai regardé les segments TCP avec Wireshark.
Chrome doit récupérer 14 éléments pour afficher le site Web, principalement des éléments statiques comme des images ou des fichiers CSS. Et cela a pris 14 TCP et cela a pris beaucoup de temps (environ 1,2 seconde). Après chaque demande d'image (par exemple), il y avait un TCP avec l'indicateur FIN
défini sur 1.
Alors qu'en est-il de Chrome vs Firefox? Chrome semble avoir un nombre maximum de connexions simultanées à un serveur de 6. Firefox a une configuration plus granulaire et distingue persistant (maxium de 6, vu dans about: config) et non persistant (les nombres maximum diffèrent beaucoup selon les sources). Mais attendez ... Les deux, Chrome et Firefox envoient HTTP /1.1 en-têtes de demande avec Connection: keep-alive
, les deux devraient donc être limités à 6 (car il s'agit d'une demande d'ouverture d'une connexion persistante).
J'ai décidé d'essayer une astuce simple et j'ai ajouté les lignes suivantes à mon .htaccess
dans le dossier racine Web:
<ifModule mod_headers.c>
Header set Connection keep-alive
</ifModule>
Le serveur répond maintenant avec:
Connection: keep-alive, close
Maintenant, j'ai jeté un coup d'œil aux segments TCP à nouveau: il n'y avait que 9 connexions de Chrome à mon serveur maintenant et seulement 3 avec le FIN
flag mis à 1. Donc, cette astuce semblait fonctionner. Mais pourquoi y avait-il ces 3 connexions, qui ont fermé la connexion après la transmission des données? Ce sont les requêtes PHP, comme en-tête HTTP X-Powered-By: PHP/5.4.11
confirmé.
Et qu'en est-il de Firefox? Il y avait encore ces 14 demandes!
Comment résoudre ce problème et faire fonctionner les processus fcgi avec keep-alive aussi?
J'ai ajouté les lignes suivantes à ma section virtualhost de la configuration httpd.conf:
KeepAlive On
KeepAliveTimeout 5
MaxKeepAliveRequests 100
et supprimé ceux ajoutés dans le .htaccess
. Maintenant, le serveur n'envoie pas de confusion - Connection: keep-alive, close
, mais, seulement Connection: keep-alive
et tout fonctionne bien!
Conclusion:
Un en-tête avec le champ de connexion défini sur
HTTP/1.1 200 OK
Connection: keep-alive, close
sera interprété par Chrome comme keep-alive
tandis que Firefox semble fermer chaque connexion. Cela semble dépendre de la mise en œuvre réelle.
Donc, si vous êtes prêt à implémenter un client pour gérer les en-têtes de réponse contenant Connection: keep-alive, close
, Je proposerais d'essayer d'utiliser keep-alive si vous avez besoin de plusieurs requêtes. La pire chose qui puisse arriver: le serveur fermera la connexion et vous devez vous reconnecter (c'est exactement l'autre option que vous auriez eue!)
Cela signifie que le serveur ne fera pas de connexions persistantes et fermera la connexion après cette demande.
Vous utilisez HTTP/1.1
et vous spécifiez Connection: keep-alive
.
En dessous de HTTP/1.1
toutes les connexions sont maintenues par défaut, et le Connection: keep-alive
l'en-tête est obsolète, vous ne devez donc pas l'envoyer.
Connection: keep-alive
est un petit hack utilisé dans le soi-disant HTTP/1.0+
journées. (Le +
signifie "hacks nécessaires pour le faire fonctionner.")
Dans HTTP: The Definitive Guide de Brian Totty, Marjorie Sayer, Sailu Reddy, Anshu Aggarwal, David Gourley par O'Reilly nous lisons:
Keep-alive est déconseillé et n'est plus documenté dans la spécification HTTP/1.1 actuelle. Cependant, la prise de contact permanente est toujours relativement utilisée par les navigateurs et les serveurs, donc les implémenteurs HTTP doivent être prêts à interagir avec elle.
Le serveur peut être "interopérant" et vous trolling pour être redondant.
La réponse est à RFC 7230 - 6.1. Connexion . Ça dit:
La valeur du champ d'en-tête Connection a la grammaire suivante:
Connection = 1#connection-option connection-option = token
Dans le langage Internet RFC, le 1#connection-option
signifie au moins un et au plus n'importe quel nombre de connection-option
. Cela signifie qu'il peut y avoir plusieurs options parmi lesquelles le récepteur choisira celui qu'il préfère. Ce n'est pas une ambiguïté, c'est un choix.