5. Protokoły komunikacyjne

5.1. HTTP


Protokół HTTP (ang. Hypertext transfer protocol) jest standardem (protokołem) komunikacji internetowej między klientami i serwerami. Został on opracowany i jest nadzorowany przez organizację World Wide Web Consortium (W3C, www.w3.org). Najnowsza wersja, HTTP/3, została opublikowana w 2022 roku:

Internet Engineering Task Force, Request for Comments 9114 - HTTP/3

(o protokole HTTP przeczytasz także w tym rozdziale tego podręcznika)

Historia protokołu HTTP sięga początku lat 90-tych XX-wieku. Od tamtego znacząco zmienił się sposób tworzenia usług w sieci Web. Podczas gdy początkowo były to powiązane ze sobą za pomocą odnośników statyczne dokumenty zapisane w języku HTML. Stopniowo jednak sieć ewoluowała w kierunku coraz bardziej dynamicznego dostarczania treści. Istotnie wzrosły też wymagania, np. w obszarze szybkości czy też bezpieczeństwa. Skutkowało to ujawnieniem się pewnych problemów, które wynikają z ograniczeń protokołu, zwłaszcza w jego starszych wersjach. Przyjrzyjmy się krótko tym problemom oraz rozwiązaniom, które można zastosować, aby wyeliminować lub zminimalizować ich skutki.

1. Bezstanowość protokołu HTTP
HTTP jest protokołem bezstanowym, co oznacza, że każde żądanie i odpowiedź są niezależne od innych. Bez zastosowania dodatkowych mechanizmów serwer nie jest w stanie powiązać ze sobą logicznie kolejnych interakcji, nawet jeśli pochodzą od tego samego klienta. Innymi słowy, protokół HTTP nie definiuje pojęcia takiego jak sesja komunikacji z danym klientem. W zdecydowanej większości zachodzi więc konieczność stosowania dodatkowych mechanizmów do zarządzania sesjami, takich jak:
  • ciasteczka (ang. cookies) - są to małe pliki tekstowe zapisywane przez przeglądarkę na urządzeniu użytkownika, służące do przechowywania informacji identyfikujących daną sesję;
    O zastosowaniach ciasteczek przeczytasz w artykule "Po co są ciasteczka?" a także na portalu MDN w artykule "Using HTTP cookies"
  • obsługa sesji po stronie serwera - serwer musi przechowywać informacje na temat każdej otwartej sesji, aby móc dostarczyć danemu użytkownikowi spersonalizowaną stronę (np. o treści adekwatnej do uprawnień przypisanych do danego konta);
  • tokeny autoryzacyjne, np. JWT (ang. JSON Web Token) - służą do przekazywaniu do klienta informacji m.in. o uwierzytelnionej sesji; więcej o tokenach JWT przeczytasz w tym artykule podręcznika.
2. Wydajność i opóźnienia w HTTP/1.0 i HTTP/1.1
Starsze wersje protokołu HTTP charakteryzują się ograniczeniami wydajnościowymi, które szczególnie uwidaczniają się w przypadku stron i aplikacji, które muszą ładować wiele zasobów, takich jak pliki CSS, obrazy, skrypty JavaScript. Ograniczenia te wynikają bezpośrednio z cech protokołu HTTP:
  • pobieranie jednego zasobu na jedno połączenie TCP (HTTP/1.0) - wykorzystywany w warstwie transportowej protokół TCP cechuje się pewnym narzutem przy zestawianiu połączenia (wynika to m.in. z zastosowanego tam mechanizmu potwierdzeń znanego jako tzw. three-way handshake); w starej wersji protokołu HTTP otwierane było osobne połączenie dla każdego pobieranego zasobu a następnie połączenie było zamykane; rozwiązanie przyszło wraz z protokołem HTTP/1.1, który pozwolił na przesyłanie kolejno wielu żądań w ramach jednego połączenia TCP;
  • blokowanie sekwencji żądań (ang. head-of-line blocking) (HTTP/1.1) - przesyłane przez przeglądarkę żądania muszą być przetwarzane przez serwer kolejno; wydłużony czas przetwarzania jednego żądania, blokuje możliwość obsługi kolejnych żądań, co w konsekwencji wstrzymuje całą komunikację;
  • brak równoczesności - aby zminimalizować efekt blokowania sekwencji żądań, w protokole HTTP/1.1. przeglądarki  otwierają wiele równoległych połączeń TCP do jednego serwera, co z kolei niepotrzebnie zwiększa obciążenie sieci.
Rozwiązania (częściowo wprowadzone w HTTP/2 i HTTP/3):
  • protokół HTTP/2 wprowadza multiplexing, który umożliwia przetwarzanie wielu żądań w jednym połączeniu TCP;
  • protokół HTTP/3 eliminuje problem head-of-line blocking dzięki wykorzystaniu protokołu QUIC, który w warstwie transportowej korzysta z protokołu UDP w miejsce TCP; więcej o korzyściach płynących ze stosowania protokołu HTTP/3 przeczytasz z artykułu "Nadeszła era HTTP/3. Co wnosi nowy standard komunikacji?"
3. Skalowalność i obciążenie serwera
Wskazane powyżej częste otwieranie i zamykanie połączeń TCP dla każdego żądania (HTTP/1.0) znacząco obciążało serwer w aplikacjach z dużą liczbą użytkowników. W tym aspekcie multipleksing wprowadzony w HTTP/2 również okazał się pomocny. Inną techniką, która pozwala zmniejszyć obciążenie serwera jest wykorzystanie dedykowanej sieci serwerów dostarczających statyczne treści (np. muzykę, filmy itp.), czyli ang. Content Delivery Network (CDN).

4. Problemy z bezpieczeństwem
HTTP w wersji podstawowej przesyła dane w sposób nieszyfrowany, co oznacza, że dane mogą być przechwycone przez atakującego. Ma to szczególne znaczenie np. w przypadku danych logowania, danych kart płatniczych i innych informacji osobistych, ale także ciekawym elementem informacji są same adresy odwiedzanych stron.
Użycie protokołu HTTPS (HTTP Secure), który dodaje do HTTP protokół szyfrowania TLS (ang. Transport Layer Security) rozwiązuje część problemów związanych z bezpieczeństwem, ale nie gwarantuje, że aplikacja internetowa (rozumiana jako całość) korzystająca z tego protokołu jest z automatu w 100% bezpieczna. Zagadnienia bezpieczeństwa są na tyle obszerne, że poświęcony im został cały rozdział niniejszego podręcznika - zapraszam do lektury!

5. Umiarkowana efektywność przesyłania danych
Protokół HTTP/1.1 wymaga przesyłania nagłówków w każdym żądaniu i odpowiedzi. Nagłówki te przesyłane są w formie tekstowej i zajmują średnio po kilkaset bajtów na każde żądanie (czasami więcej, gdy dojdą np. liczne ciasteczka). W przypadku, gdy rozmiar użytecznych danych jest znacząco większy od tej liczby, to nie stanowi to istotnego problemu, jednakże często występują sytuacje, gdy narzut ten nie jest zaniedbywalny (np. pobieranie wielu małych grafik, plików JS, CSS itp.). Konsekwencją jest przede wszystkim dłuższa transmisja danych poprzez sieć, co skutkuje np. dłuższym ładowaniem stron.
Jako rozwiązanie protokół HTTP/2 wprowadza kompresję nagłówków (HPACK), co znacznie zmniejsza ilość danych przesyłanych między klientem a serwerem. Więcej na ten temat przeczytasz w tych artykułach:
6. Brak wsparcia dla aktualizacji w czasie rzeczywistym
Protokół HTTP został zaprojektowany w oparciu o model żądań i odpowiedzi, gdzie klient wysyła zapytanie, a serwer na nie odpowiada. Nie ma więc natywnego wsparcia dla aktualizacji danych w czasie rzeczywistym ani innych form stałego połączenia między klientem a serwerem. W konsekwencji aplikacje wymagające aktualizacji w czasie rzeczywistym (np. czaty, gry online, strony z notowaniami giełdowymi) muszą korzystać z dodatkowych rozwiązań, takich jak:
  • technika Long Polling - polega na nawiązaniu połączenia HTTP przez klienta, jednakże odpowiedź nie musi zostać odesłana natychmiast; w niektórych implementacjach serwer może także podtrzymywać połączenie i przesyłać kolejne aktualizacje odpowiedzi w późniejszym czasie,
  • protokół WebSocket - jest to uzupełnienie do protokołu HTTP pozwalające na komunikację dwukierunkową; więcej przeczytasz na tej stronie podręcznika,
  • Server-Sent Events (SSE) - sformalizowany mechanizm przesyłania komunikatów od serwera do klienta, przy czym najpierw klient musi nawiązać połączenie z serwerem, które następnie jest podtrzymywane; więcej przeczytasz w artykule "Stream updates with server-sent events".
7. Problemy z cache'owaniem
Aby skrócić czas ładowania stron www, protokól HTTP/1.1 wprowadził mechanizmy sterowania procesem cache'owania (np. poprzez nagłówki Cache-Control), czyli przechowywania przez przeglądarkę internetową pobranych już elementów strony. Dzięki temu przy kolejnych odsłonach nie jest potrzebne pobieranie od początku wszystkich zasobów, gdyż przeglądarka wykorzystuje już te zapisane wcześniej w pamięci podręcznej. Wykorzystanie tego mechanizmu daje istotne korzyści, ale wymaga od programisty zaplanowania, m.in. które z zasobów mogą podlegać przechowywaniu przez przeglądarkę, na jak długo oraz co zrobić w przypadku, gdy zasób na serwerze trzeba zaktualizować, ale przeglądarka dostała informację, że może przez pewien czasu nie pobierać danego zasobu z serwera... Wiele szczegółów na ten temat znajdziesz w artykule "HTTP caching" na portalu MDN.

Niniejszy artykuł na pewno nie omawia wszystkich zagadnień związanych bezpośrednio ze specyfiką protokołu HTTP, ale stanowi punkt zaczepienia do dalszych samodzielnych poszukiwań.