HTTP/2 Server Threads

· Fonctionnalités

Depuis sgcWebSockets 2024.2.0, le serveur HTTP/2 a été amélioré pour la réception des requêtes HTTP/2. Désormais, par défaut, lorsque le serveur reçoit une nouvelle requête HTTP/2, celle-ci est mise en file d'attente et dispatchée par l'un des threads du pool de threads. Cela évite le problème quand plusieurs requêtes sont envoyées sur la même connexion et traitées séquentiellement.

Voici les différences entre HTTP 1.1 et HTTP 2.0 :

HTTP 1.1

 Dans le comportement HTTP traditionnel, lorsqu'on fait plusieurs requêtes sur la même connexion, le client doit attendre la réponse de chaque requête avant d'envoyer la suivante. Cette approche séquentielle augmente fortement le temps de chargement des ressources d'un site web. Pour répondre à ce problème, HTTP/1.1 a introduit une fonctionnalité appelée pipelining, qui permet à un client d'envoyer plusieurs requêtes sans attendre les réponses du serveur. Le serveur répond alors au client dans le même ordre que celui de réception des requêtes.

Si le pipelining semblait être une solution, il a rencontré des difficultés :


Pour optimiser le chargement des pages depuis les serveurs prenant en charge HTTP/1.1, les navigateurs ont mis en place une solution de contournement. Ils ouvrent six à huit connexions parallèles vers le serveur, ce qui permet de transmettre simultanément plusieurs requêtes. Ce parallélisme vise à atténuer les problèmes liés au pipelining et à améliorer les temps de chargement globaux des pages.

Le choix de six à huit connexions parallèles par les navigateurs repose sur des considérations d'optimisation. Les raisons spécifiques de ce nombre relèvent d'un compromis entre l'utilisation des ressources, l'efficacité réseau et l'évitement des goulets d'étranglement potentiels. 

HTTP 2.0

En réponse aux contraintes rencontrées avec le pipelining, HTTP/2 a introduit une fonctionnalité appelée multiplexage. Le multiplexage permet une communication plus efficace entre le client et le serveur en autorisant la transmission simultanée de plusieurs requêtes et réponses sur une seule connexion.

HTTP/2 utilise un mécanisme de framing binaire : les messages HTTP sont décomposés en unités plus petites et indépendantes appelées frames. Ces frames peuvent être entrelacées et envoyées sur la connexion indépendamment les unes des autres. À la réception, les frames sont réassemblées pour reconstruire le message HTTP original.

Ce mécanisme de framing binaire est fondamental pour le multiplexage dans HTTP/2. Il permet au navigateur d'envoyer plusieurs requêtes sur la même connexion sans rencontrer de problèmes de blocage. C'est pourquoi les navigateurs comme Chrome utilisent le même identifiant de connexion pour les requêtes HTTP/2, ce qui permet une communication efficace et ininterrompue entre le client et le serveur.

En somme, le multiplexage de HTTP/2, rendu possible par le framing binaire, améliore l'efficacité et la vitesse d'échange des données entre clients et serveurs en facilitant la transmission simultanée de plusieurs requêtes et réponses sur une seule connexion.

Composant TsgcWebSocketHTTPServer

Pour améliorer les performances du protocole HTTP/2, les requêtes sont dispatchées par défaut dans un pool de threads (32 par défaut) chaque fois qu'une nouvelle requête HTTP/2 est reçue par le serveur. Cela évite les attentes lorsqu'une seule connexion envoie beaucoup de requêtes concurrentes qui devraient sinon être traitées séquentiellement (dans le contexte du thread de connexion) en l'absence de ce pool.

Le comportement du PoolOfThreads peut être configuré avec les propriétés suivantes.


Pour affiner les requêtes, en choisissant lesquelles doivent être traitées dans le pool de threads (parce qu'elles consomment du temps) tandis que d'autres peuvent l'être dans le thread de connexion, tu peux utiliser l'événement OnHttp2BeforeAsyncRequest. Cet événement est déclenché avant la mise en file de la requête dans le pool de threads ; utilise le paramètre Async pour définir si la requête est threadée ou non.
procedure OnHTTP2BeforeAsyncRequest(Sender: TObject; Connection: TsgcWSConnection; const ARequestInfo: TIdHTTPRequestInfo; var Async: Boolean);
begin
  if ARequestInfo.Document = '/time-consuming-request' then
    ASync := False;
end;