Vanaf sgcWebSockets 2024.2.0 is de HTTP/2-server verbeterd bij het ontvangen van HTTP/2-aanvragen. Standaard wordt elke nieuwe HTTP/2-aanvraag nu in de wachtrij geplaatst en afgehandeld door één van de threads uit de threadpool. Dit voorkomt het probleem dat optreedt als meerdere aanvragen via dezelfde verbinding worden verzonden en sequentieel worden verwerkt.
Zie hieronder de verschillen tussen HTTP 1.1 en HTTP 2.0:
HTTP 1.1
Bij het traditionele HTTP-gedrag moet de client, wanneer hij meerdere aanvragen over dezelfde verbinding doet, op het antwoord van elke aanvraag wachten voordat hij de volgende verzendt. Deze sequentiële aanpak verhoogt de laadtijd van bronnen van een website aanzienlijk. Om dit aan te pakken introduceerde HTTP/1.1 een functie genaamd pipelining, waarmee een client meerdere aanvragen kan verzenden zonder op de antwoorden van de server te wachten. De server beantwoordt de client vervolgens in dezelfde volgorde als waarin hij de aanvragen heeft ontvangen.
Hoewel pipelining een oplossing leek, kende het uitdagingen:
- Negeren door de server of antwoordcorruptie: sommige servers negeerden gepipelinede aanvragen of beschadigden de antwoorden, wat leidde tot onbetrouwbare communicatie.
- Head-of-Line Blocking: de eerste aanvraag in de pipeline kon volgende aanvragen blokkeren en zo de verwerking van andere aanvragen vertragen. Dit verschijnsel, bekend als head-of-line blocking, leidde tot langzamere laadtijden van pagina's.
Om het laden van pagina's vanaf HTTP/1.1-servers te optimaliseren, implementeerden webbrowsers een tussenoplossing. Zo openen ze zes tot acht parallelle verbindingen naar de server, waardoor meerdere aanvragen tegelijk kunnen worden verzonden. Dit parallellisme moet de problemen van pipelining beperken en de totale laadtijden verbeteren.
De keuze voor zes tot acht parallelle verbindingen door de webbrowsers is gebaseerd op optimalisatieoverwegingen. De specifieke redenen voor dit aantal hebben te maken met een afweging tussen het gebruik van resources, netwerkefficiëntie en het vermijden van mogelijke knelpunten.
HTTP 2.0
Als reactie op de beperkingen van pipelining introduceerde HTTP/2 een functie genaamd multiplexing. Multiplexing maakt efficiëntere communicatie tussen client en server mogelijk door meerdere aanvragen en antwoorden gelijktijdig over één verbinding te verzenden.
HTTP/2 gebruikt een binair frame-mechanisme, wat betekent dat HTTP-berichten worden opgesplitst in kleinere, onafhankelijke eenheden, frames genaamd. Deze frames kunnen door elkaar worden gemengd en onafhankelijk van elkaar over de verbinding worden verzonden. Aan de ontvangende kant worden de frames weer in elkaar gezet om het oorspronkelijke HTTP-bericht te reconstrueren.
Dit binaire frame-mechanisme is essentieel om multiplexing in HTTP/2 mogelijk te maken. Het stelt de browser in staat om meerdere aanvragen over dezelfde verbinding te verzenden zonder blokkeerproblemen. Daarom gebruiken browsers zoals Chrome dezelfde verbindings-ID voor HTTP/2-aanvragen, wat efficiënte en ononderbroken communicatie tussen client en server mogelijk maakt.
Kortom: de multiplexingfunctie van HTTP/2, mogelijk gemaakt door het binaire frame-mechanisme, vergroot de efficiëntie en snelheid van de gegevensuitwisseling tussen clients en servers door gelijktijdige verzending van meerdere aanvragen en antwoorden over één verbinding.
TsgcWebSocketHTTPServer-component
Om de prestaties van het HTTP/2-protocol te verbeteren, worden de aanvragen standaard afgehandeld in een threadpool (standaard 32) telkens wanneer de server een nieuwe HTTP/2-aanvraag ontvangt. Dit voorkomt wachttijden wanneer één verbinding veel gelijktijdige aanvragen verzendt die anders sequentieel (in de context van de connectiethread) zouden moeten worden verwerkt zonder deze threadpool.
Het gedrag van de PoolOfThreads kun je configureren met de volgende eigenschappen.
- HTTP2Options.PoolOfThreads.Enabled: (standaard true) zorgt dat de http/2-aanvragen worden afgehandeld in de threadpool in plaats van in de connectiethread.
- HTTP2Options.Threads: (standaard 32) het aantal threads dat wordt gebruikt om HTTP/2-aanvragen te verwerken. Stel een getal in dat past bij het aantal processoren van je server.
Om de aanvragen fijn af te stemmen en te kiezen welke in de threadpool moeten worden verwerkt (omdat ze tijdrovend zijn) en welke in de connectiethread kunnen worden verwerkt, kun je het event OnHttp2BeforeAsyncRequest gebruiken. Dit event wordt geactiveerd voordat de aanvraag in de threadpool wordt geplaatst; gebruik de parameter Async om in te stellen of de aanvraag wel of niet in een aparte thread wordt afgehandeld.
procedure OnHTTP2BeforeAsyncRequest(Sender: TObject; Connection: TsgcWSConnection; const ARequestInfo: TIdHTTPRequestInfo; var Async: Boolean);
begin
if ARequestInfo.Document = '/time-consuming-request' then
ASync := False;
end;
