5. Flux et Multiplexage
Un "flux" (stream) est une séquence indépendante et bidirectionnelle de trames échangées entre le client et le serveur au sein d'une connexion HTTP/2. Les flux présentent plusieurs caractéristiques importantes:
-
Une seule connexion HTTP/2 peut contenir plusieurs flux ouverts simultanément, les deux points de terminaison entrelaçant les trames de plusieurs flux.
-
Les flux peuvent être établis et utilisés unilatéralement ou partagés par le client ou le serveur.
-
Les flux peuvent être fermés par l'un ou l'autre des points de terminaison.
-
L'ordre dans lequel les trames sont envoyées sur un flux est significatif. Les destinataires traitent les trames dans l'ordre où elles sont reçues. En particulier, l'ordre des trames HEADERS et DATA est sémantiquement significatif.
-
Les flux sont identifiés par un entier. Les identifiants de flux sont attribués aux flux par le point de terminaison qui initie le flux.
5.1. États des Flux
Le cycle de vie d'un flux est illustré dans la Figure 2.
+--------+
send PP | | recv PP
,--------+ idle +--------.
/ | | \
v +--------+ v
+----------+ | +----------+
| | | send H / | |
,-----+ reserved | | recv H | reserved +-----.
| | (local) | | | (remote) | |
| +---+------+ v +------+---+ |
| | +--------+ | |
| | recv ES | | send ES | |
| send H | ,-------+ open +-------. | recv H |
| | / | | \ | |
| v v +---+----+ v v |
| +----------+ | +----------+ |
| | half- | | | half- | |
| | closed | | send R / | closed | |
| | (remote) | | recv R | (local) | |
| +----+-----+ | +-----+----+ |
| | | | |
| | send ES / | recv ES / | |
| | send R / v send R / | |
| | recv R +--------+ recv R | |
| send R / `----------->| |<-----------' send R / |
| recv R | closed | recv R |
`----------------------->| |<----------------------'
+--------+
send: endpoint sends this frame
recv: endpoint receives this frame
H: HEADERS frame (with implied CONTINUATION frames)
PP: PUSH_PROMISE frame (with implied CONTINUATION frames)
ES: END_STREAM flag
R: RST_STREAM frame
Figure 2: États des Flux
Notez que ce diagramme montre uniquement les transitions d'état des flux et les trames et drapeaux qui affectent ces changements d'état. À cet égard, les trames CONTINUATION n'entraînent pas de transitions d'état et font effectivement partie de HEADERS ou PUSH_PROMISE qu'elles suivent. Aux fins des transitions d'état, le drapeau END_STREAM est traité comme un événement séparé de la trame qui le porte; une trame HEADERS avec le drapeau END_STREAM défini peut provoquer deux transitions d'état.
Les deux points de terminaison ont une vue subjective de l'état d'un flux qui pourrait être différente lorsque les trames sont en transit. Les points de terminaison ne coordonnent pas la création des flux; ils sont créés unilatéralement par l'un ou l'autre point de terminaison. Les conséquences négatives d'une inadéquation des états sont limitées à l'état "closed" après l'envoi de RST_STREAM, où des trames pourraient être reçues pendant un certain temps après la fermeture.
Les flux ont les états suivants:
idle: Tous les flux commencent dans l'état "idle".
Les transitions suivantes sont valides à partir de cet état:
-
L'envoi ou la réception d'une trame HEADERS fait passer le flux à l'état "open". L'identifiant de flux est sélectionné comme décrit dans la Section 5.1.1. La même trame HEADERS peut également faire passer immédiatement un flux à l'état "half-closed".
-
L'envoi d'une trame PUSH_PROMISE sur un autre flux réserve le flux idle qui est identifié pour une utilisation ultérieure. L'état du flux pour le flux réservé passe à "reserved (local)".
-
La réception d'une trame PUSH_PROMISE sur un autre flux réserve un flux idle qui est identifié pour une utilisation ultérieure. L'état du flux pour le flux réservé passe à "reserved (remote)".
-
Notez que la trame PUSH_PROMISE n'est pas envoyée sur le flux idle mais fait référence au flux nouvellement réservé dans le champ Promised Stream ID.
La réception d'une trame autre que HEADERS ou PRIORITY sur un flux dans cet état DOIT être traitée comme une erreur de connexion (Section 5.4.1) de type PROTOCOL_ERROR.
reserved (local): Un flux dans l'état "reserved (local)" est un flux qui a été promis en envoyant une trame PUSH_PROMISE. Une trame PUSH_PROMISE réserve un flux idle en associant le flux à un flux ouvert qui a été initié par le pair distant (voir Section 8.4).
Dans cet état, seules les transitions suivantes sont possibles:
-
Le point de terminaison peut envoyer une trame HEADERS. Cela fait passer le flux à l'état "half-closed (remote)".
-
L'un ou l'autre des points de terminaison peut envoyer une trame RST_STREAM pour faire passer le flux à l'état "closed". Cela libère la réservation du flux.
Un point de terminaison NE DOIT PAS envoyer d'autre type de trame que HEADERS, RST_STREAM ou PRIORITY dans cet état.
Une trame PRIORITY ou WINDOW_UPDATE PEUT être reçue dans cet état. La réception de tout type de trame autre que RST_STREAM, PRIORITY ou WINDOW_UPDATE sur un flux dans cet état DOIT être traitée comme une erreur de connexion (Section 5.4.1) de type PROTOCOL_ERROR.
reserved (remote): Un flux dans l'état "reserved (remote)" a été réservé par un pair distant.
Dans cet état, seules les transitions suivantes sont possibles:
-
La réception d'une trame HEADERS fait passer le flux à l'état "half-closed (local)".
-
L'un ou l'autre des points de terminaison peut envoyer une trame RST_STREAM pour faire passer le flux à l'état "closed". Cela libère la réservation du flux.
Un point de terminaison PEUT envoyer une trame PRIORITY dans cet état pour reprioriser le flux réservé. Un point de terminaison NE DOIT PAS envoyer d'autre type de trame que RST_STREAM, WINDOW_UPDATE ou PRIORITY dans cet état.
La réception de tout type de trame autre que HEADERS, RST_STREAM ou PRIORITY sur un flux dans cet état DOIT être traitée comme une erreur de connexion (Section 5.4.1) de type PROTOCOL_ERROR.
open: Un flux dans l'état "open" peut être utilisé par les deux pairs pour envoyer des trames de tout type. Dans cet état, les pairs émetteurs observent les limites de contrôle de flux au niveau du flux annoncées (Section 5.2).
À partir de cet état, l'un ou l'autre des points de terminaison peut envoyer une trame avec un drapeau END_STREAM défini, ce qui fait passer le flux dans l'un des états "half-closed". Un point de terminaison qui envoie un drapeau END_STREAM fait passer l'état du flux à "half-closed (local)"; un point de terminaison qui reçoit un drapeau END_STREAM fait passer l'état du flux à "half-closed (remote)".
L'un ou l'autre des points de terminaison peut envoyer une trame RST_STREAM à partir de cet état, ce qui le fait passer immédiatement à "closed".
half-closed (local): Un flux qui est dans l'état "half-closed (local)" ne peut pas être utilisé pour envoyer des trames autres que WINDOW_UPDATE, PRIORITY et RST_STREAM.
Un flux passe de cet état à "closed" lorsqu'une trame est reçue avec le drapeau END_STREAM défini ou lorsque l'un ou l'autre des pairs envoie une trame RST_STREAM.
Un point de terminaison peut recevoir tout type de trame dans cet état. Fournir un crédit de contrôle de flux en utilisant des trames WINDOW_UPDATE est nécessaire pour continuer à recevoir des trames contrôlées par le flux. Dans cet état, un récepteur peut ignorer les trames WINDOW_UPDATE, qui pourraient arriver pendant une courte période après l'envoi d'une trame avec le drapeau END_STREAM défini.
Les trames PRIORITY reçues dans cet état sont utilisées pour reprioriser les flux qui dépendent du flux identifié.
half-closed (remote): Un flux qui est "half-closed (remote)" n'est plus utilisé par le pair pour envoyer des trames. Dans cet état, un point de terminaison n'est plus obligé de maintenir une fenêtre de contrôle de flux de récepteur.
Si un point de terminaison reçoit des trames supplémentaires, autres que WINDOW_UPDATE, PRIORITY ou RST_STREAM, pour un flux qui est dans cet état, il DOIT répondre avec une erreur de flux (Section 5.4.2) de type STREAM_CLOSED.
Un flux qui est "half-closed (remote)" peut être utilisé par le point de terminaison pour envoyer des trames de tout type. Dans cet état, le point de terminaison continue d'observer les limites de contrôle de flux au niveau du flux annoncées (Section 5.2).
Un flux peut passer de cet état à "closed" en envoyant une trame avec le drapeau END_STREAM défini ou lorsque l'un ou l'autre des pairs envoie une trame RST_STREAM.
closed: L'état "closed" est l'état terminal.
Un point de terminaison NE DOIT PAS envoyer de trames autres que PRIORITY sur un flux fermé. Un point de terminaison qui reçoit une trame autre que PRIORITY après avoir reçu un RST_STREAM DOIT traiter cela comme une erreur de flux (Section 5.4.2) de type STREAM_CLOSED. De même, un point de terminaison qui reçoit des trames après avoir reçu une trame avec le drapeau END_STREAM défini DOIT traiter cela comme une erreur de connexion (Section 5.4.1) de type STREAM_CLOSED, à moins que la trame ne soit autorisée comme décrit ci-dessous.
Les trames WINDOW_UPDATE ou RST_STREAM peuvent être reçues dans cet état pendant une courte période après l'envoi d'une trame DATA ou HEADERS contenant un drapeau END_STREAM. Jusqu'à ce que le pair distant reçoive et traite RST_STREAM ou la trame portant le drapeau END_STREAM, il pourrait envoyer des trames de ces types. Les points de terminaison DOIVENT ignorer les trames WINDOW_UPDATE ou RST_STREAM reçues dans cet état, bien que les points de terminaison PUISSENT choisir de traiter les trames qui arrivent un temps significatif après l'envoi de END_STREAM comme une erreur de connexion (Section 5.4.1) de type PROTOCOL_ERROR.
Les trames PRIORITY peuvent être envoyées sur des flux fermés pour prioriser les flux qui dépendent du flux fermé. Les points de terminaison DEVRAIENT traiter les trames PRIORITY, bien qu'elles puissent être ignorées si le flux a été retiré de l'arbre de dépendance (voir Section 5.3.3 de [RFC7540]).
Si cet état est atteint à la suite de l'envoi d'une trame RST_STREAM, le pair qui reçoit le RST_STREAM pourrait avoir déjà envoyé -- ou mis en file d'attente pour l'envoi -- des trames sur le flux qui ne peuvent pas être retirées. Un point de terminaison DOIT ignorer les trames qu'il reçoit sur des flux fermés après avoir envoyé une trame RST_STREAM. Un point de terminaison PEUT choisir de limiter la période pendant laquelle il ignore les trames et de traiter les trames qui arrivent après ce temps comme étant en erreur.
Les trames contrôlées par le flux (c'est-à-dire DATA) reçues après l'envoi de RST_STREAM sont comptées dans la fenêtre de contrôle de flux de la connexion. Même si ces trames peuvent être ignorées, parce qu'elles sont envoyées avant que l'expéditeur ne reçoive le RST_STREAM, l'expéditeur considérera que les trames comptent contre la fenêtre de contrôle de flux.
Un point de terminaison pourrait recevoir une trame PUSH_PROMISE après avoir envoyé RST_STREAM. PUSH_PROMISE fait passer un flux à l'état "reserved" même si le flux associé a été réinitialisé. Par conséquent, un RST_STREAM est nécessaire pour fermer un flux promis non désiré.
En l'absence de règles plus spécifiques, les implémentations DEVRAIENT traiter la réception d'une trame qui n'est pas expressément autorisée dans la description d'un état comme une erreur de connexion (Section 5.4.1) de type PROTOCOL_ERROR. Notez que PRIORITY peut être envoyé et reçu dans n'importe quel état de flux.
Les règles de cette section ne s'appliquent qu'aux trames définies dans ce document. La réception de trames dont la sémantique est inconnue ne peut pas être traitée comme une erreur, car les conditions d'envoi et de réception de ces trames sont également inconnues; voir Section 5.5.
Un exemple des transitions d'état pour un échange requête/réponse HTTP se trouve dans la Section 8.8. Un exemple des transitions d'état pour le push serveur se trouve dans les Sections 8.4.1 et 8.4.2.
5.1.1. Identifiants de Flux
Les flux sont identifiés par un entier non signé de 31 bits. Les flux initiés par un client DOIVENT utiliser des identifiants de flux à numérotation impaire; ceux initiés par le serveur DOIVENT utiliser des identifiants de flux à numérotation paire. Un identifiant de flux de zéro (0x00) est utilisé pour les messages de contrôle de connexion; l'identifiant de flux zéro ne peut pas être utilisé pour établir un nouveau flux.
L'identifiant d'un flux nouvellement établi DOIT être numériquement supérieur à tous les flux que le point de terminaison initiateur a ouverts ou réservés. Cela régit les flux qui sont ouverts en utilisant une trame HEADERS et les flux qui sont réservés en utilisant PUSH_PROMISE. Un point de terminaison qui reçoit un identifiant de flux inattendu DOIT répondre avec une erreur de connexion (Section 5.4.1) de type PROTOCOL_ERROR.
Une trame HEADERS fera passer le flux initié par le client identifié par l'identifiant de flux dans l'en-tête de trame de "idle" à "open". Une trame PUSH_PROMISE fera passer le flux initié par le serveur identifié par le champ Promised Stream ID dans la charge utile de trame de "idle" à "reserved (local)" ou "reserved (remote)". Lorsqu'un flux sort de l'état "idle", tous les flux dans l'état "idle" qui auraient pu être ouverts par le pair avec un identifiant de flux de valeur inférieure passent immédiatement à "closed". Autrement dit, un point de terminaison peut sauter un identifiant de flux, l'effet étant que le flux sauté est immédiatement fermé.
Les identifiants de flux ne peuvent pas être réutilisés. Les connexions de longue durée peuvent entraîner un point de terminaison épuisant la plage disponible d'identifiants de flux. Un client incapable d'établir un nouvel identifiant de flux peut établir une nouvelle connexion pour de nouveaux flux. Un serveur incapable d'établir un nouvel identifiant de flux peut envoyer une trame GOAWAY afin que le client soit forcé d'ouvrir une nouvelle connexion pour de nouveaux flux.
5.1.2. Concurrence des Flux
Un pair peut limiter le nombre de flux actifs simultanément en utilisant le paramètre SETTINGS_MAX_CONCURRENT_STREAMS (voir Section 6.5.2) dans une trame SETTINGS. Le paramètre de flux simultanés maximum est spécifique à chaque point de terminaison et s'applique uniquement au pair qui reçoit le paramètre. Autrement dit, les clients spécifient le nombre maximum de flux simultanés que le serveur peut initier, et les serveurs spécifient le nombre maximum de flux simultanés que le client peut initier.
Les flux qui sont dans l'état "open" ou dans l'un des états "half-closed" comptent pour le nombre maximum de flux qu'un point de terminaison est autorisé à ouvrir. Les flux dans l'un de ces trois états comptent pour la limite annoncée dans le paramètre SETTINGS_MAX_CONCURRENT_STREAMS. Les flux dans l'un des états "reserved" ne comptent pas pour la limite de flux.
Les points de terminaison NE DOIVENT PAS dépasser la limite définie par leur pair. Un point de terminaison qui reçoit une trame HEADERS qui fait dépasser sa limite de flux simultanés annoncée DOIT traiter cela comme une erreur de flux (Section 5.4.2) de type PROTOCOL_ERROR ou REFUSED_STREAM. Le choix du code d'erreur détermine si le point de terminaison souhaite activer la nouvelle tentative automatique (voir Section 8.7 pour plus de détails).
Un point de terminaison qui souhaite réduire la valeur de SETTINGS_MAX_CONCURRENT_STREAMS à une valeur inférieure au nombre actuel de flux ouverts peut soit fermer les flux qui dépassent la nouvelle valeur, soit permettre aux flux de se terminer.
5.2. Contrôle de Flux
L'utilisation de flux pour le multiplexage introduit une contention sur l'utilisation de la connexion TCP, ce qui entraîne des flux bloqués. Un schéma de contrôle de flux garantit que les flux sur la même connexion n'interfèrent pas de manière destructive les uns avec les autres. Le contrôle de flux est utilisé à la fois pour les flux individuels et pour la connexion dans son ensemble.
HTTP/2 fournit un contrôle de flux grâce à l'utilisation de la trame WINDOW_UPDATE (Section 6.9).
5.2.1. Principes du Contrôle de Flux
Le contrôle de flux des flux HTTP/2 vise à permettre l'utilisation d'une variété d'algorithmes de contrôle de flux sans nécessiter de changements de protocole. Le contrôle de flux dans HTTP/2 présente les caractéristiques suivantes:
-
Le contrôle de flux est spécifique à une connexion. Le contrôle de flux HTTP/2 opère entre les points de terminaison d'un seul saut et non sur l'ensemble du chemin de bout en bout.
-
Le contrôle de flux est basé sur des trames WINDOW_UPDATE. Les récepteurs annoncent combien d'octets ils sont prêts à recevoir sur un flux et pour l'ensemble de la connexion. Il s'agit d'un schéma basé sur le crédit.
-
Le contrôle de flux est directionnel avec un contrôle global fourni par le récepteur. Un récepteur PEUT choisir de définir n'importe quelle taille de fenêtre qu'il désire pour chaque flux et pour l'ensemble de la connexion. Un expéditeur DOIT respecter les limites de contrôle de flux imposées par un récepteur. Les clients, serveurs et intermédiaires annoncent tous indépendamment leur fenêtre de contrôle de flux en tant que récepteur et respectent les limites de contrôle de flux définies par leur pair lors de l'envoi.
-
La valeur initiale de la fenêtre de contrôle de flux est de 65 535 octets pour les nouveaux flux et pour l'ensemble de la connexion.
-
Le type de trame détermine si le contrôle de flux s'applique à une trame. Parmi les trames spécifiées dans ce document, seules les trames DATA sont soumises au contrôle de flux; tous les autres types de trames ne consomment pas d'espace dans la fenêtre de contrôle de flux annoncée. Cela garantit que les trames de contrôle importantes ne sont pas bloquées par le contrôle de flux.
-
Un point de terminaison peut choisir de désactiver son propre contrôle de flux, mais un point de terminaison ne peut pas ignorer les signaux de contrôle de flux de son pair.
-
HTTP/2 définit uniquement le format et la sémantique de la trame WINDOW_UPDATE (Section 6.9). Ce document ne stipule pas comment un récepteur décide quand envoyer cette trame ou la valeur qu'il envoie, ni ne spécifie comment un expéditeur choisit d'envoyer des paquets. Les implémentations peuvent sélectionner n'importe quel algorithme qui répond à leurs besoins.
Les implémentations sont également responsables de la priorisation de l'envoi des requêtes et des réponses, du choix de la manière d'éviter le blocage en tête de ligne pour les requêtes, et de la gestion de la création de nouveaux flux. Les choix d'algorithmes pour ceux-ci pourraient interagir avec n'importe quel algorithme de contrôle de flux.
5.2.2. Utilisation Appropriée du Contrôle de Flux
Le contrôle de flux est défini pour protéger les points de terminaison qui fonctionnent sous des contraintes de ressources. Par exemple, un proxy doit partager la mémoire entre de nombreuses connexions et pourrait également avoir une connexion en amont lente et une connexion en aval rapide. Le contrôle de flux traite les cas où le récepteur est incapable de traiter les données sur un flux mais souhaite continuer à traiter d'autres flux sur la même connexion.
Les déploiements qui ne nécessitent pas cette capacité peuvent annoncer une fenêtre de contrôle de flux de taille maximale (2^31-1) et peuvent maintenir cette fenêtre en envoyant une trame WINDOW_UPDATE lorsque des données sont reçues. Cela désactive effectivement le contrôle de flux pour ce récepteur. À l'inverse, un expéditeur est toujours soumis à la fenêtre de contrôle de flux annoncée par le récepteur.
Les déploiements avec des ressources contraintes (par exemple, la mémoire) peuvent employer le contrôle de flux pour limiter la quantité de mémoire qu'un pair peut consommer. Notez cependant que cela peut conduire à une utilisation sous-optimale des ressources réseau disponibles si le contrôle de flux est activé sans connaissance du produit bande passante * délai (voir [RFC7323]).
Même avec une pleine conscience du produit bande passante * délai actuel, la mise en œuvre du contrôle de flux peut être difficile. Les points de terminaison DOIVENT lire et traiter les trames HTTP/2 du tampon de réception TCP dès que les données sont disponibles. L'échec de la lecture rapide pourrait conduire à un blocage lorsque des trames critiques, telles que WINDOW_UPDATE, ne sont pas lues et prises en compte. La lecture rapide des trames n'expose pas les points de terminaison aux attaques d'épuisement des ressources, car le contrôle de flux HTTP/2 limite les engagements de ressources.
5.2.3. Performance du Contrôle de Flux
Si un point de terminaison ne peut pas garantir que son pair dispose toujours d'un espace de fenêtre de contrôle de flux disponible supérieur au produit bande passante * délai du pair sur cette connexion, son débit de réception sera limité par le contrôle de flux HTTP/2. Cela entraînera une dégradation des performances.
L'envoi de trames WINDOW_UPDATE opportunes peut améliorer les performances. Les points de terminaison voudront équilibrer le besoin d'améliorer le débit de réception avec le besoin de gérer les risques d'épuisement des ressources et devraient prendre soigneusement note de la Section 10.5 pour définir leur stratégie de gestion des tailles de fenêtre.
5.3. Priorisation
Dans un protocole multiplexé comme HTTP/2, la priorisation de l'allocation de bande passante et de ressources de calcul aux flux peut être cruciale pour obtenir de bonnes performances. Un mauvais schéma de priorisation peut entraîner de mauvaises performances pour HTTP/2. Sans parallélisme au niveau de la couche TCP, les performances pourraient être significativement pires que HTTP/1.1.
Un bon schéma de priorisation bénéficie de l'application de connaissances contextuelles telles que le contenu des ressources, la manière dont les ressources sont interconnectées et la manière dont ces ressources seront utilisées par un pair. En particulier, les clients peuvent posséder des connaissances sur la priorité des requêtes qui sont pertinentes pour la priorisation du serveur. Dans ces cas, le fait que les clients fournissent des informations de priorité peut améliorer les performances.
5.3.1. Contexte sur la Priorité dans RFC 7540
RFC 7540 a défini un système riche pour signaler la priorité des requêtes. Cependant, ce système s'est avéré complexe et n'a pas été uniformément mis en œuvre.
Le schéma flexible signifiait qu'il était possible pour les clients d'exprimer des priorités de manières très différentes, avec peu de cohérence dans les approches adoptées. Pour les serveurs, la mise en œuvre d'un support générique pour le schéma était complexe. La mise en œuvre des priorités était inégale tant chez les clients que chez les serveurs. De nombreux déploiements de serveurs ont ignoré les signaux des clients lors de la priorisation de leur traitement des requêtes.
En bref, la signalisation de priorisation dans RFC 7540 [RFC7540] n'a pas été couronnée de succès.
5.3.2. Signalisation de Priorité dans ce Document
Cette mise à jour de HTTP/2 déprécie la signalisation de priorité définie dans RFC 7540 [RFC7540]. La majeure partie du texte lié aux signaux de priorité n'est pas incluse dans ce document. La description des champs de trame et une partie de la gestion obligatoire sont conservées pour garantir que les implémentations de ce document restent interopérables avec les implémentations qui utilisent la signalisation de priorité décrite dans RFC 7540.
Une description approfondie du schéma de priorité RFC 7540 reste dans la Section 5.3 de [RFC7540].
La signalisation d'informations de priorité est nécessaire pour obtenir de bonnes performances dans de nombreux cas. Là où la signalisation d'informations de priorité est importante, les points de terminaison sont encouragés à utiliser un schéma alternatif, tel que le schéma décrit dans [HTTP-PRIORITY].
Bien que la signalisation de priorité de RFC 7540 n'ait pas été largement adoptée, les informations qu'elle fournit peuvent toujours être utiles en l'absence de meilleures informations. Les points de terminaison qui reçoivent des signaux de priorité dans les trames HEADERS ou PRIORITY peuvent bénéficier de l'application de ces informations. En particulier, les implémentations qui consomment ces signaux ne bénéficieraient pas de l'abandon de ces signaux de priorité en l'absence d'alternatives.
Les serveurs DEVRAIENT utiliser d'autres informations contextuelles pour déterminer la priorité des requêtes en l'absence de tout signal de priorité. Les serveurs PEUVENT interpréter l'absence complète de signaux comme une indication que le client n'a pas implémenté la fonctionnalité. Les valeurs par défaut décrites dans la Section 5.3.5 de [RFC7540] sont connues pour avoir de mauvaises performances dans la plupart des conditions, et leur utilisation est peu susceptible d'être délibérée.
5.4. Gestion des Erreurs
Le cadrage HTTP/2 permet deux classes d'erreurs:
-
Une condition d'erreur qui rend l'ensemble de la connexion inutilisable est une erreur de connexion.
-
Une erreur dans un flux individuel est une erreur de flux.
Une liste de codes d'erreur est incluse dans la Section 7.
Il est possible qu'un point de terminaison rencontre des trames qui provoqueraient plusieurs erreurs. Les implémentations PEUVENT découvrir plusieurs erreurs pendant le traitement, mais elles DEVRAIENT signaler au maximum une erreur de flux et une erreur de connexion en conséquence.
La première erreur de flux signalée pour un flux donné empêche toute autre erreur sur ce flux d'être signalée. En comparaison, le protocole permet plusieurs trames GOAWAY, bien qu'un point de terminaison DEVRAIT ne signaler qu'un seul type d'erreur de connexion à moins qu'une erreur ne soit rencontrée pendant l'arrêt gracieux. Si cela se produit, un point de terminaison PEUT envoyer une trame GOAWAY supplémentaire avec le nouveau code d'erreur, en plus de tout GOAWAY précédent qui contenait NO_ERROR.
Si un point de terminaison détecte plusieurs erreurs différentes, il PEUT choisir de signaler l'une de ces erreurs. Si une trame provoque une erreur de connexion, cette erreur DOIT être signalée. De plus, un point de terminaison PEUT utiliser tout code d'erreur applicable lorsqu'il détecte une condition d'erreur; un code d'erreur générique (tel que PROTOCOL_ERROR ou INTERNAL_ERROR) peut toujours être utilisé à la place de codes d'erreur plus spécifiques.
5.4.1. Gestion des Erreurs de Connexion
Une erreur de connexion est toute erreur qui empêche le traitement ultérieur de la couche de trame ou corrompt tout état de connexion.
Un point de terminaison qui rencontre une erreur de connexion DEVRAIT d'abord envoyer une trame GOAWAY (Section 6.8) avec l'identifiant de flux du dernier flux qu'il a reçu avec succès de son pair. La trame GOAWAY inclut un code d'erreur (Section 7) qui indique pourquoi la connexion se termine. Après avoir envoyé la trame GOAWAY pour une condition d'erreur, le point de terminaison DOIT fermer la connexion TCP.
Il est possible que le GOAWAY ne soit pas reçu de manière fiable par le point de terminaison récepteur. En cas d'erreur de connexion, GOAWAY ne fournit qu'une tentative au mieux pour communiquer avec le pair sur la raison pour laquelle la connexion est terminée.
Un point de terminaison peut terminer une connexion à tout moment. En particulier, un point de terminaison PEUT choisir de traiter une erreur de flux comme une erreur de connexion. Les points de terminaison DEVRAIENT envoyer une trame GOAWAY lors de la fin d'une connexion, à condition que les circonstances le permettent.
5.4.2. Gestion des Erreurs de Flux
Une erreur de flux est une erreur liée à un flux spécifique qui n'affecte pas le traitement d'autres flux.
Un point de terminaison qui détecte une erreur de flux envoie une trame RST_STREAM (Section 6.4) qui contient l'identifiant de flux du flux où l'erreur s'est produite. La trame RST_STREAM inclut un code d'erreur qui indique le type d'erreur.
Un RST_STREAM est la dernière trame qu'un point de terminaison peut envoyer sur un flux. Le pair qui envoie la trame RST_STREAM DOIT être prêt à recevoir toutes les trames qui ont été envoyées ou mises en file d'attente pour l'envoi par le pair distant. Ces trames peuvent être ignorées, sauf lorsqu'elles modifient l'état de connexion (tel que l'état maintenu pour la compression de section de champ (Section 4.3) ou le contrôle de flux).
Normalement, un point de terminaison NE DEVRAIT PAS envoyer plus d'une trame RST_STREAM pour un flux. Cependant, un point de terminaison PEUT envoyer des trames RST_STREAM supplémentaires s'il reçoit des trames sur un flux fermé après plus d'un temps d'aller-retour. Ce comportement est autorisé pour traiter les implémentations mal comportées.
Pour éviter les boucles, un point de terminaison NE DOIT PAS envoyer un RST_STREAM en réponse à une trame RST_STREAM.
5.4.3. Terminaison de Connexion
Si la connexion TCP est fermée ou réinitialisée alors que des flux restent dans les états "open" ou "half-closed", alors les flux affectés ne peuvent pas être automatiquement retentés (voir Section 8.7 pour plus de détails).
5.5. Extension de HTTP/2
HTTP/2 permet l'extension du protocole. Dans les limites décrites dans cette section, les extensions de protocole peuvent être utilisées pour fournir des services supplémentaires ou modifier tout aspect du protocole. Les extensions ne sont efficaces que dans le cadre d'une seule connexion HTTP/2.
Cela s'applique aux éléments de protocole définis dans ce document. Cela n'affecte pas les options existantes pour étendre HTTP, telles que la définition de nouvelles méthodes, codes d'état ou champs (voir Section 16 de [HTTP]).
Les extensions sont autorisées à utiliser de nouveaux types de trames (Section 4.1), de nouveaux paramètres (Section 6.5) ou de nouveaux codes d'erreur (Section 7). Les registres pour gérer ces points d'extension sont définis dans la Section 11 de [RFC7540].
Les implémentations DOIVENT ignorer les valeurs inconnues ou non prises en charge dans tous les éléments de protocole extensibles. Les implémentations DOIVENT rejeter les trames qui ont des types inconnus ou non pris en charge. Cela signifie que n'importe lequel de ces points d'extension peut être utilisé en toute sécurité par les extensions sans arrangement ou négociation préalable. Cependant, les trames d'extension qui apparaissent au milieu d'un bloc de champ (Section 4.3) ne sont pas autorisées; celles-ci DOIVENT être traitées comme une erreur de connexion (Section 5.4.1) de type PROTOCOL_ERROR.
Les extensions DEVRAIENT éviter de modifier les éléments de protocole définis dans ce document ou les éléments pour lesquels aucun mécanisme d'extension n'est défini. Cela inclut les modifications de la disposition des trames, les ajouts ou modifications de la manière dont les trames sont composées en messages HTTP (Section 8.1), la définition de champs de pseudo-en-tête, ou les modifications de tout élément de protocole qu'un point de terminaison conforme pourrait traiter comme une erreur de connexion (Section 5.4.1).
Une extension qui modifie des éléments ou états de protocole existants DOIT être négociée avant d'être utilisée. Par exemple, une extension qui modifie la disposition de la trame HEADERS ne peut pas être utilisée tant que le pair n'a pas donné un signal positif que cela est acceptable. Dans ce cas, il pourrait également être nécessaire de coordonner le moment où la disposition révisée entre en vigueur. Par exemple, traiter des trames autres que les trames DATA comme contrôlées par le flux nécessite un changement de sémantique que les deux points de terminaison doivent comprendre, donc cela ne peut être fait que par négociation.
Ce document n'impose pas de méthode spécifique pour négocier l'utilisation d'une extension, mais note qu'un paramètre (Section 6.5.2) pourrait être utilisé à cette fin. Si les deux pairs définissent une valeur qui indique la volonté d'utiliser l'extension, alors l'extension peut être utilisée. Si un paramètre est utilisé pour la négociation d'extension, la valeur initiale DOIT être définie de telle manière que l'extension soit initialement désactivée.
Chapitre 5 terminé!