Od sgcWebSockets 2024.2.0 serwer HTTP/2 został ulepszony pod kątem odbierania żądań HTTP/2. Teraz domyślnie, gdy serwer otrzymuje nowe żądanie HTTP/2, jest ono kolejkowane i wysyłane przez jeden z wątków puli wątków. Pozwala to uniknąć problemu, gdy kilka żądań jest wysyłanych przez to samo połączenie i są one przetwarzane sekwencyjnie.
Poniżej zobaczysz różnice między HTTP 1.1 a HTTP 2.0:
HTTP 1.1
W tradycyjnym zachowaniu HTTP, podczas wysyłania wielu żądań przez to samo połączenie, klient musi czekać na odpowiedź na każde żądanie, zanim wyśle kolejne. To sekwencyjne podejście znacznie wydłuża czas ładowania zasobów witryny. Aby rozwiązać ten problem, HTTP/1.1 wprowadził funkcję zwaną pipelining, która pozwala klientowi wysyłać wiele żądań bez oczekiwania na odpowiedzi serwera. Serwer z kolei odpowiada klientowi w tej samej kolejności, w jakiej otrzymał żądania.
Chociaż pipelining wydawał się rozwiązaniem, napotkał wyzwania:
- Ignorowanie przez serwer lub uszkodzenie odpowiedzi: niektóre serwery albo ignorowały żądania pipelined, albo uszkadzały odpowiedzi, co prowadziło do niewiarygodnej komunikacji.
- Blokowanie head-of-line: pierwsze żądanie w potoku mogło blokować kolejne żądania, powodując opóźnienie w przetwarzaniu innych żądań. To zjawisko, znane jako blokowanie head-of-line, skutkowało wolniejszym ładowaniem stron.
Aby zoptymalizować ładowanie stron z serwerów obsługujących HTTP/1.1, przeglądarki internetowe wdrożyły obejście. Otwierają sześć-osiem równoległych połączeń z serwerem, umożliwiając jednoczesną transmisję wielu żądań. Ta równoległość ma na celu złagodzenie problemów związanych z pipelining i poprawę ogólnych czasów ładowania stron.
Wybór sześciu-ośmiu równoległych połączeń przez przeglądarki opiera się na rozważaniach optymalizacyjnych. Konkretne powody wyboru tej liczby mogą wiązać się z kompromisem między wykorzystaniem zasobów, efektywnością sieci a unikaniem potencjalnych wąskich gardeł.
HTTP 2.0
W odpowiedzi na ograniczenia napotkane w pipelining, HTTP/2 wprowadził funkcję zwaną multiplexing. Multiplexing umożliwia bardziej efektywną komunikację między klientem a serwerem dzięki jednoczesnej transmisji wielu żądań i odpowiedzi przez pojedyncze połączenie.
HTTP/2 wykorzystuje mechanizm ramkowania binarnego, co oznacza, że wiadomości HTTP są dzielone na mniejsze, niezależne jednostki zwane ramkami. Ramki te mogą być przeplatane i wysyłane przez połączenie niezależnie od siebie. Po stronie odbiorczej ramki są ponownie składane w celu odtworzenia oryginalnej wiadomości HTTP.
Ten mechanizm ramkowania binarnego jest fundamentalny dla osiągnięcia multipleksowania w HTTP/2. Pozwala przeglądarce wysyłać wiele żądań przez to samo połączenie bez napotykania problemów z blokowaniem. W rezultacie przeglądarki takie jak Chrome wykorzystują to samo ID połączenia dla żądań HTTP/2, umożliwiając efektywną i nieprzerwaną komunikację między klientem a serwerem.
W istocie funkcja multipleksowania HTTP/2, włączona przez mechanizm ramkowania binarnego, zwiększa wydajność i szybkość wymiany danych między klientami a serwerami, ułatwiając jednoczesną transmisję wielu żądań i odpowiedzi przez pojedyncze połączenie.
Komponent TsgcWebSocketHTTPServer
Aby poprawić wydajność protokołu HTTP/2, żądania są domyślnie wysyłane w puli wątków (domyślnie 32) za każdym razem, gdy serwer otrzymuje nowe żądanie HTTP/2. Pozwala to uniknąć oczekiwania, gdy pojedyncze połączenie wysyła wiele równoczesnych żądań, które wymagałyby przetwarzania sekwencyjnego (w kontekście wątku połączenia) bez tej puli wątków.
Zachowanie PoolOfThreads można skonfigurować w następujących właściwościach.
- HTTP2Options.PoolOfThreads.Enabled: (domyślnie true) włącza wysyłanie żądań http/2 w puli wątków zamiast w wątku połączenia.
- HTTP2Options.Threads: (domyślnie 32) liczba wątków używanych do obsługi żądań HTTP/2. Ustaw liczbę odpowiadającą liczbie procesorów twojego serwera.
Aby precyzyjnie dostroić żądania, wybierając, które muszą być przetwarzane w puli wątków (ponieważ są czasochłonne), a które mogą być przetwarzane w wątku połączenia, możesz użyć zdarzenia OnHttp2BeforeAsyncRequest. To zdarzenie jest wywoływane przed zakolejkowaniem żądania w puli wątków — użyj parametru Async , aby ustawić, czy żądanie jest wątkowane, czy nie.
procedure OnHTTP2BeforeAsyncRequest(Sender: TObject; Connection: TsgcWSConnection; const ARequestInfo: TIdHTTPRequestInfo; var Async: Boolean);
begin
if ARequestInfo.Document = '/time-consuming-request' then
ASync := False;
end;
