HTTP/2

Ramkowanie binarne, multipleksowanie i server push w HTTP/2.

Dlaczego Potrzebowaliśmy Nowego HTTP? Ograniczenia HTTP/1.1

Przez prawie dwie dekady protokół HTTP/1.1 był koniem pociągowym, który napędzał rozwój World Wide Web. Wprowadził on połączenia trwałe, pozwalając na wysyłanie wielu żądań i odpowiedzi przez jedno połączenie TCP, co było ogromnym postępem w stosunku do jego poprzednika, HTTP/1.0. Jednak w miarę jak strony internetowe ewoluowały z prostych dokumentów tekstowych w złożone, bogate w zasoby aplikacje z dziesiątkami skryptów, arkuszy stylów i obrazów, ograniczenia HTTP/1.1 stały się znaczącym wąskim gardłem wydajności.

Najważniejszym i krytycznym problemem w HTTP/1.1 jest tak zwane . Mimo korzystania z trwałego połączenia, przeglądarka mogła wysłać tylko jedno żądanie na raz na tym połączeniu i musiała czekać na pełną odpowiedź, zanim mogła wysłać kolejne. Jedno powolne żądanie, na przykład o duży obraz lub wolno działający punkt końcowy API, blokowało wszystkie inne żądania w kolejce, pozostawiając połączenie bezczynnym i opóźniając renderowanie reszty strony.

Deweloperzy wymyślili sprytne, ale skomplikowane obejścia, aby złagodzić ten problem, takie jak używanie wielu połączeń TCP do jednej nazwy hosta, fragmentacja domen czy łączenie plików. Te techniki dodawały złożoności i narzutu. Stało się jasne, że sam protokół potrzebuje fundamentalnego przeprojektowania, aby sprostać wymaganiom nowoczesnej sieci. To doprowadziło do rozwoju HTTP/2, który w dużej mierze opierał się na eksperymentalnym protokole SPDY firmy Google i został oficjalnie ustandaryzowany w 2015 roku.

Koncepcja Podstawowa 1: Warstwa Ramek Binarnych

Najbardziej fundamentalną i rewolucyjną zmianą wprowadzoną w HTTP/2 jest . HTTP/1.1 był protokołem tekstowym. Jego komunikaty, w tym linie żądań, nagłówki i ciała, były wysyłane jako czytelny dla człowieka tekst oddzielony znakami nowej linii. Chociaż było to świetne do debugowania, było nieefektywne do parsowania przez maszyny i podatne na błędy.

HTTP/2 zastępuje to protokołem binarnym. Cała komunikacja jest dzielona na mniejsze, zarządzalne i zoptymalizowane maszynowo jednostki zwane ramkami. Ta zmiana z tekstu na format binarny ma kilka głębokich implikacji:

  • Wydajność: format binarny jest szybszy do parsowania i bardziej zwarty.
  • Solidność: mniej dwuznaczności niż w komunikatach tekstowych.
  • Nowe możliwości: to właśnie ten model umożliwia multipleksowanie i priorytetyzację.

Struktura ramki HTTP/2

Każda ramka w HTTP/2 ma ściśle zdefiniowaną strukturę. Składa się ze stałego 9-bajtowego nagłówka, po którym następuje ładunek o zmiennej długości.

Długość (24 bity)
Wskazuje długość ładunku ramki w bajtach.
Typ (8 bitów)
Definiuje typ ramki i sposób interpretacji ładunku.
Flagi (8 bitów)
Zestaw flag zależnych od typu ramki.
Identyfikator strumienia (31 bitów)
Określa, do którego strumienia należy dana ramka.
Ładunek ramki (zmienny)
Właściwa zawartość ramki, zależna od jej typu.

Popularne typy ramek

Najczęściej spotkasz między innymi:

  • DATA: ciało wiadomości.
  • HEADERS: nagłówki HTTP.
  • PRIORITY: priorytet strumienia.
  • SETTINGS: konfiguracja połączenia.
  • PUSH_PROMISE: zapowiedź server push.

Koncepcja Podstawowa 2: Strumienie i Multipleksowanie

Warstwa ramek binarnych bezpośrednio umożliwia flagową funkcję HTTP/2: . Ta funkcja całkowicie rozwiązuje problem blokowania na czele kolejki znany z HTTP/1.1.

Strumienie: wirtualne kanały

W ramach jednego połączenia HTTP/2 klient i serwer mogą ustanowić wiele niezależnych, dwukierunkowych sekwencji ramek zwanych strumieniami. Jedno połączenie TCP działa więc jak wspólna autostrada, a każdy strumień jak osobny pas.

  • Każdy strumień ma własny identyfikator.
  • Żądanie i odpowiedź odbywają się w tym samym strumieniu.
  • Strumienie klienta mają identyfikatory nieparzyste, a serwera parzyste.
  • Jedno połączenie może przenosić setki lub tysiące strumieni naraz.

Jak multipleksowanie usuwa blokowanie HOL

Ponieważ komunikacja jest podzielona na małe ramki, serwer może przeplatać odpowiedzi z wielu strumieni na tym samym połączeniu. Opóźnienie jednego dużego zasobu nie blokuje już innych odpowiedzi, więc CSS, JS i małe zasoby mogą dotrzeć szybciej.

Dzięki temu znika potrzeba sztucznych obejść, takich jak wielokrotne połączenia do jednego hosta. Efekt to szybsze ładowanie stron, mniejsze zużycie zasobów i lepsze wykorzystanie sieci.

Koncepcja Podstawowa 3: Wypychanie Serwerowe (Server Push)

W klasycznym HTTP to klient inicjuje komunikację: pobiera HTML, analizuje go i dopiero potem żąda CSS oraz JavaScriptu. To tworzy kaskadę żądań i opóźnień.

HTTP/2 dodał mechanizm , w którym serwer może przewidzieć potrzebne zasoby i wysłać je z wyprzedzeniem.

Jak działa Server Push

  1. Żądanie klienta: przeglądarka prosi o `index.html`.
  2. Analiza serwera: serwer wie, że zaraz potrzebne będą też `style.css` i `app.js`.
  3. PUSH_PROMISE: serwer zapowiada i wysyła te zasoby, zanim klient o nie poprosi.
  4. Oryginalna odpowiedź: klient nadal dostaje żądany HTML.
  5. Buforowanie po stronie klienta: przeglądarka może użyć zasobów od razu podczas renderu.

Server Push potrafił skrócić czas ładowania, ale wymagał ostrożnego użycia. Wypychanie zasobów już obecnych w cache było marnotrawstwem, dlatego w praktyce nowoczesne wdrożenia częściej stawiają dziś na `preload`.

Inne Główne Usprawnienia w HTTP/2

Poza trzema głównymi koncepcjami HTTP/2 wprowadził jeszcze kilka istotnych ulepszeń wpływających na wydajność.

Kompresja nagłówków (HPACK)
Zmniejsza narzut wynikający z wielokrotnego przesyłania podobnych nagłówków przy kolejnych żądaniach.
Priorytetyzacja strumieni
Pozwala klientowi zasugerować, które zasoby są ważniejsze dla renderu i powinny być dostarczone wcześniej.
Jedno połączenie na domenę
Multipleksowanie eliminuje potrzebę otwierania wielu połączeń TCP do tego samego hosta.
Domyślnie bezpieczny w praktyce
Choć specyfikacja nie wymusza TLS, realne przeglądarki używają HTTP/2 praktycznie wyłącznie z HTTPS.