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 (zazwyczaj ograniczone do 6 przez przeglądarkę), fragmentacja domen (domain sharding) 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ść: Formaty binarne są znacznie bardziej zwarte i szybsze do parsowania przez komputery niż formaty tekstowe, co zmniejsza narzut obliczeniowy.
  • Solidność: Ramkowanie binarne jest mniej dwuznaczne i podatne na błędy niż parsowanie tekstu ze zmiennymi białymi znakami i zakończeniami linii.
  • Umożliwienie Nowych Funkcji: To ustrukturyzowane, ramkowe podejście jest kluczem, który odblokowuje najpotężniejsze funkcje HTTP/2, takie jak multipleksowanie, priorytetyzacja strumieni i server push.

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ść (2424 bity)
Liczba całkowita bez znaku wskazująca długość ładunku ramki w bajtach.
Typ (88 bitów)
Definiuje typ ramki. To określa, jak należy interpretować ładunek.
Flagi (88 bitów)
Zestaw ośmiu jednobitowych flag specyficznych dla typu ramki, używanych do modyfikacji jej zachowania.
Identyfikator Strumienia (3131 bitów)
Unikalny identyfikator strumienia, do którego należy ta ramka. Jest to kluczowe dla multipleksowania.
Ładunek Ramki (Zmienny)
Rzeczywista zawartość ramki, której struktura jest określona przez pole Typ.

Popularne Typy Ramek

Niektóre z najważniejszych typów ramek to:

  • DATA: Przenosi ciało wiadomości dla żądania lub odpowiedzi.
  • HEADERS: Zawiera nagłówki HTTP dla żądania lub odpowiedzi.
  • PRIORITY: Używana do określania priorytetu strumienia.
  • SETTINGS: Przekazuje parametry konfiguracyjne dla połączenia.
  • PUSH_PROMISE: Używana przez serwer do inicjowania wypychania zasobów.

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 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. Można myśleć o pojedynczym połączeniu TCP jak o głównej autostradzie, a o każdym strumieniu jak o dedykowanym pasie na tej autostradzie. Jeden pas może być dla dokumentu HTML, inny dla pliku CSS, a trzeci dla obrazu. Wszystkie te pasy istnieją na tej samej autostradzie i mogą być używane w tym samym czasie.

  • Każdy strumień ma przypisany unikalny identyfikator strumienia.
  • Żądanie i odpowiadająca mu odpowiedź odbywają się w tym samym strumieniu.
  • Strumienie inicjowane przez klienta zawsze mają nieparzyste identyfikatory, podczas gdy strumienie inicjowane przez serwer (używane do Server Push) mają parzyste.
  • Jedno połączenie może obsługiwać setki lub tysiące równoczesnych strumieni.

Jak Multipleksowanie Rozwiązuje Blokowanie HOL

Ponieważ komunikacja jest podzielona na małe, niezależne ramki, z których każda jest oznaczona identyfikatorem swojego strumienia, klient i serwer mogą przeplatać ramki z wielu strumieni na tym samym połączeniu. Jeśli odpowiedź na żądanie o duży obraz (w strumieniu 5) jest opóźniona, serwer wciąż może wysyłać ramki dla pliku CSS (w strumieniu 3) i pliku JavaScript (w strumieniu 7) bez czekania. Kiedy ramki dotrą do klienta, są one ponownie składane w odpowiednie strumienie za pomocą identyfikatora strumienia.

To równoległe przetwarzanie w ramach jednego połączenia oznacza, że wolna odpowiedź już nie blokuje szybszych. Eliminuje to potrzebę obejść, takich jak wielokrotne połączenia, co prowadzi do szybszego ładowania stron, mniejszego zużycia zasobów zarówno po stronie klienta, jak i serwera, oraz bardziej wydajnego wykorzystania sieci.

Koncepcja Podstawowa 3: Wypychanie Serwerowe (Server Push)

Tradycyjnie, komunikacja HTTP jest ściśle inicjowana przez klienta. Przeglądarka żąda pliku HTML, parsuje go, znajduje odniesienia do plików CSS i JavaScript, a następnie wysyła nowe żądania o te zasoby. Tworzy to kaskadę żądań, z nieuniknionymi opóźnieniami między każdym krokiem.

HTTP/2 wprowadza potężny nowy mechanizm zwany , który pozwala serwerowi przerwać ten cykl żądanie-odpowiedź. Inteligentny serwer może przewidzieć, jakich zasobów będzie potrzebował klient i proaktywnie „wepchnąć” je do pamięci podręcznej klienta, zanim zostaną one nawet zażądane.

Jak Działa Server Push

  1. Żądanie Klienta: Przeglądarka wysyła normalne żądanie o zasób, na przykład index.html.
  2. Analiza Serwera: Serwer otrzymuje żądanie. Wie, że każda przeglądarka żądająca index.html natychmiast będzie potrzebowała również style.css i app.js do wyrenderowania strony.
  3. Serwer Wypycha Zasoby: Przed wysłaniem odpowiedzi na żądanie o index.html, serwer wysyła do klienta specjalne ramki PUSH_PROMISE. Te ramki mówią w efekcie: „Zamierzam wysłać Ci style.css i app.js, więc nie musisz o nie prosić”. Następnie wysyła dane dla tych zasobów na nowych, inicjowanych przez serwer strumieniach.
  4. Oryginalna Odpowiedź: Serwer wysyła oryginalną odpowiedź dla index.html.
  5. Klient Odbiera i Buforuje: Przeglądarka otrzymuje wszystkie trzy zasoby niemal jednocześnie. Kiedy zaczyna parsować HTML i znajduje linki do plików CSS i JS, zdaje sobie sprawę, że są one już w jej pamięci podręcznej i może ich natychmiast użyć.

Server Push może znacznie skrócić czas ładowania strony, eliminując opóźnienia związane z koniecznością indywidualnego żądania każdego zasobu przez przeglądarkę. Musi być jednak używany ostrożnie. Wypychanie zasobów, które klient już ma w pamięci podręcznej, jest marnotrawstwem. Nowoczesne najlepsze praktyki często preferują użycie wskazówek `Preload` zamiast Server Push ze względu na złożoność jego implementacji i zachowania buforowania.

Inne Główne Usprawnienia w HTTP/2

Poza trzema głównymi koncepcjami, HTTP/2 wprowadził kilka innych krytycznych ulepszeń, które przyczyniają się do jego wyższej wydajności.

Kompresja Nagłówków (HPACK)
W HTTP/1.1 nagłówki są wysyłane jako zwykły tekst przy każdym żądaniu i odpowiedzi, często ze znaczną redundancją. Na przykład przeglądarka może wysyłać identyczne nagłówki User-Agent i Accept dziesiątki razy podczas ładowania jednej strony. To składa się na znaczny narzut. HTTP/2 wprowadza wysoce efektywny format kompresji nagłówków o nazwie HPACK. Używa on statycznej tabeli popularnych nagłówków i dynamicznej tabeli, która jest budowana w trakcie trwania połączenia, aby kodować nagłówki w znacznie bardziej zwartej formie. To radykalnie zmniejsza ilość danych, które muszą być wysłane, zwłaszcza w sieciach mobilnych.
Priorytetyzacja Strumieni
Dzięki multipleksowaniu przeglądarka może wysyłać wiele żądań naraz, ale nie wszystkie zasoby są równie ważne dla wyrenderowania strony. Na przykład, blokujący renderowanie plik CSS jest ważniejszy niż obraz na dole strony. HTTP/2 pozwala klientowi na przypisanie priorytetu i zależności do każdego strumienia. Może poinformować serwer: „Ten strumień zależy od innego strumienia” lub „Ten strumień jest ważniejszy”. Pozwala to serwerowi na bardziej inteligentne alokowanie zasobów, takich jak CPU i pasmo, aby dostarczyć najważniejsze zasoby w pierwszej kolejności, co dodatkowo optymalizuje czas ładowania strony.
Jedno Połączenie na Domenę
Rozwiązując problem blokowania HOL poprzez multipleksowanie, HTTP/2 eliminuje potrzebę wielokrotnych połączeń TCP do jednego źródła. Pojedyncze połączenie jest bardziej wydajne. Zmniejsza narzut związany z uzgadnianiem TCP i TLS, zużywa mniej zasobów systemowych (gniazd, pamięci) i pozwala na lepszą kontrolę przeciążenia sieci, ponieważ algorytm TCP ma dokładniejszy obraz warunków sieciowych na jednym, długo żyjącym połączeniu.
Domyślnie Bezpieczny (w praktyce)
Chociaż sama specyfikacja HTTP/2 nie narzuca użycia szyfrowania, wszystkie główne implementacje przeglądarek (Chrome, Firefox, Safari, Edge) wymagają, aby HTTP/2 był uruchamiany przez szyfrowane połączenie TLS (HTTPS). To sprawiło, że nowoczesna sieć stała się znacznie bezpieczniejsza. Negocjacja użycia HTTP/2 odbywa się podczas uzgadniania TLS za pomocą mechanizmu o nazwie ALPN (Application-Layer Protocol Negotiation).
    HTTP/2 | Teleinf Edu