Uczę się o protokole HTTP / 2. Jest to protokół binarny z małymi ramkami wiadomości. Umożliwia multipleksowanie strumieniowe przez pojedyncze połączenie TCP. Pod względem koncepcyjnym wydaje się bardzo podobny do WebSockets.
Czy są plany przestarzałych gniazd sieciowych i zastąpienia ich jakimś rodzajem żądań HTTP / 2 bez nagłówków i wiadomości push inicjowanych przez serwer? A może WebSockets uzupełnią HTTP / 2?
Odpowiedzi:
Z tego co zrozumiałem HTTP / 2 nie zastępuje websocket, ale ma na celu standaryzację protokołu SPDY.
W HTTP / 2 funkcja push-server jest używana za sceną, aby usprawnić ładowanie zasobów przez klienta z przeglądarki. Jako programista tak naprawdę nie dbasz o to podczas tworzenia. Jednak w przypadku Websocket deweloper może korzystać z interfejsu API, który może odbierać i przekazywać wiadomości za pomocą unikalnego połączenia pełnego dupleksu.
To nie są te same rzeczy i powinny się wzajemnie uzupełniać.
źródło
Po zakończeniu czytania specyfikacji HTTP / 2 myślę, że HTTP / 2 robi przestarzałe gniazda sieciowe dla większości przypadków użycia, ale może nie wszystkie.
PUSH_PROMISE
(potocznie znany jako push serwera) nie jest tutaj problemem. To tylko optymalizacja wydajności.Głównym przypadkiem użycia Websockets w przeglądarce jest umożliwienie dwukierunkowego przesyłania danych. Myślę więc, że pytanie PO brzmi, czy HTTP / 2 lepiej radzi sobie z włączaniem dwukierunkowego przesyłania strumieniowego w przeglądarce i myślę, że tak.
Przede wszystkim jest to bi-di. Wystarczy przeczytać wprowadzenie do sekcji strumieni :
Artykuły takie jak ten (połączone w innej odpowiedzi) są błędne na temat tego aspektu HTTP / 2. Mówią, że to nie bidi. Spójrz, jest jedna rzecz, która nie może się zdarzyć z HTTP / 2: Po otwarciu połączenia serwer nie może zainicjować zwykłego strumienia, tylko strumień push. Ale gdy klient otworzy strumień, wysyłając żądanie, obie strony mogą w dowolnym momencie wysłać ramki DATA przez trwałe gniazdo - pełne bidi.
Nie różni się to zbytnio od websockets: klient musi zainicjować żądanie aktualizacji websocket, zanim serwer będzie mógł również przesyłać dane.
Największą różnicą jest to, że w przeciwieństwie do gniazd sieciowych, HTTP / 2 definiuje własną semantykę multipleksowania: w jaki sposób strumienie uzyskują identyfikatory i jak ramki przenoszą identyfikator strumienia, w którym się znajdują. HTTP / 2 definiuje również semantykę kontroli przepływu w celu ustalania priorytetów strumieni. Jest to ważne w większości rzeczywistych zastosowań bidi.
(Ten zły artykuł mówi również, że standard Websocket ma multipleksowanie. Nie, nie ma. Nie jest to trudne do znalezienia, po prostu otwórz Websocket RFC 6455 i naciśnij ⌘-F i wpisz „multipleks”. Po przeczytaniu
Przekonasz się, że istnieje rozszerzenie wersji roboczej 2013 dla multipleksowania Websocket. Ale nie wiem, które przeglądarki obsługują to. Nie próbowałbym zbudować mojej aplikacji SPA z tyłu tego rozszerzenia, zwłaszcza gdy nadchodzi HTTP / 2, wsparcie może nigdy nie dotrzeć.
Multipleksowanie jest dokładnie tym, co zwykle musisz zrobić sam za każdym razem, gdy otworzysz websocket dla bidi, powiedzmy, aby zasilić reagująco aktualizującą aplikację na jednej stronie. Cieszę się, że jest w specyfikacji HTTP / 2, o którą zadbano raz na zawsze.
Jeśli chcesz wiedzieć, co potrafi HTTP / 2, po prostu spójrz na gRPC. gRPC jest zaimplementowany w HTTP / 2. Przyjrzyj się w szczególności opcji przesyłania strumieniowego w trybie half i full duplex, które oferuje gRPC. (Należy pamiętać, że gRPC obecnie nie działa w przeglądarkach, ale jest tak naprawdę dlatego, że przeglądarki (1) nie ujawniają ramki HTTP / 2 w javascript klienta i (2) zasadniczo nie obsługują zwiastunów, które są używane w specyfikacja gRPC).
Gdzie wciąż mogą znajdować się gniazda sieciowe? Duży z nich to dane binarne wypychane przez serwer-> przeglądarka. HTTP / 2 pozwala na wypychanie danych binarnych przez serwer-> przeglądarka, ale nie jest ujawnione w JS przeglądarki. W przypadku takich aplikacji, jak wypychanie ramek audio i wideo, jest to powód do korzystania z gniazd sieciowych.
Edycja: 17 stycznia 2020 r
Z czasem ta odpowiedź stopniowo rosła do góry (co jest dobre, ponieważ ta odpowiedź jest mniej więcej poprawna). Jednak wciąż pojawiają się sporadyczne komentarze mówiące, że z różnych powodów nie jest to poprawne, zwykle związane z pewnym zamieszaniem na temat
PUSH_PROMISE
tego, jak faktycznie konsumować serwer zorientowany na wiadomości -> wypychanie klienta w aplikacji na jednej stronie. Istnieje również przypadek użycia dla websockets w przeglądarce, która jest danymi binarnymi przekazywanymi przez serwer. W przypadku danych tekstowych, w tym JSON, nie używaj gniazd sieciowych, użyj SSE.Reasumując: protokół HTTP / 2 jest pełny bi-di. Jednak nowoczesne przeglądarki internetowe nie narażają zorientowanego na ramki protokołu HTTP / 2 na JavaScript . Niemniej jednak, jeśli wysyłasz wiele żądań do tego samego źródła przez połączenie HTTP / 2, pod maską cały ten ruch jest multipleksowany na jednym połączeniu (i właśnie o to nam chodzi!).
Więc jeśli chcesz zbudować aplikację do czatowania w czasie rzeczywistym, powiedzmy, gdzie musisz rozgłaszać nowe wiadomości czatu do wszystkich klientów w pokoju czatu, którzy mają otwarte połączenia, możesz (i prawdopodobnie powinien) zrobić to bez gniazd internetowych.
Używałbyś zdarzeń wysłanych przez serwer do wypychania wiadomości w dół, a aplet Fetch do wysyłania żądań w górę. Server-Sent Events (SSE) to mało znany, ale dobrze obsługiwany interfejs API, który udostępnia zorientowany na komunikaty strumień serwer-klient. Chociaż nie wygląda to tak w kliencie JavaScript, pod maską twoja przeglądarka (jeśli obsługuje HTTP / 2) ponownie użyje jednego połączenia TCP do multipleksowania wszystkich tych wiadomości. Nie ma utraty wydajności i w rzeczywistości jest to zysk w stosunku do gniazd sieciowych. Potrzebujesz wielu strumieni? Otwórz wiele źródeł zdarzeń! Zostaną dla Ciebie automatycznie zmultipleksowane.
Oprócz tego, że są bardziej wydajne pod względem zasobów i mają mniejsze opóźnienie początkowe niż uścisk strony internetowej, zdarzenia wysyłane przez serwer mają dobrą właściwość polegającą na tym, że automatycznie się wycofują i działają na HTTP / 1.1. Ale gdy masz połączenie HTTP / 2, działają one niesamowicie dobrze.
Oto dobry artykuł z przykładem realnego aktualizowania SPA.
źródło
Mówię „nie” ( gniazda sieciowe nie są przestarzałe ).
Pierwszym i najczęściej ignorowanym problemem jest to, że wypychanie HTTP / 2 nie jest egzekwowalne i może być ignorowane przez serwery proxy, routery, innych pośredników, a nawet przeglądarkę.
tj. (z wersji roboczej HTTP2):
Dlatego HTTP / 2 Push nie może zastąpić WebSockets.
Ponadto połączenia HTTP / 2 zamykają się po pewnym czasie.
Prawdą jest, że standard stanowi, że:
Ale...
Nawet jeśli to samo połączenie pozwala na wypychanie zawartości, gdy jest ona otwarta, a nawet jeśli HTTP / 2 rozwiązuje niektóre problemy z wydajnością wprowadzone przez utrzymywanie aktywności HTTP / 1.1 ... Połączenia HTTP / 2 nie są otwarte przez czas nieokreślony .
Strona internetowa nie może również ponownie zainicjować połączenia HTTP / 2 po zamknięciu (chyba że powrócimy do ciągłego pobierania).
EDYCJA (2017, dwa lata później)
Implementacje HTTP / 2 pokazują, że wiele kart / okien przeglądarki współdzieli jedno połączenie HTTP / 2, co oznacza, że
push
nigdy nie będzie wiedział, do której karty / okna należy, eliminując użyciepush
jako zamiennika Websockets.EDYCJA (2020)
Nie jestem pewien, dlaczego ludzie zaczęli głosować za odpowiedzią. Jeśli już, to lata, które upłynęły od opublikowania odpowiedzi, wykazały, że HTTP / 2 nie może zastąpić WebSockets i nie został do tego przeznaczony.
To prawda, że do tunelowania połączeń WebSocket można użyć HTTP / 2 , ale te tunelowane połączenia nadal będą wymagały protokołu WebSocket i wpłyną na sposób działania kontenera HTTP / 2.
źródło
ssh
terminala w przeglądarce to pestka przy korzystaniu z Websockets. Byłoby to całkowity ból głowy na HTTP / 2, szczególnie jeśli więcej niż jedna karta jest otwarta. A co jeśli przeglądarka (lub jeden z serwerów proxy HTTP / 2) zamknie połączenie? Czy klient może po prostu założyć, że nowe dane nie są dostępne? wróciliśmy do głosowania.onclose
oddzwanianie, więc odpytywanie nie jest konieczne. Jeśli chodzi o multipleksowanie, myślę, że był to raczej wybór niż wybór.keep-alive
nie powiodło się, a jedynym sposobem uniknięcia trafienia „pierwszego w linii” było ryzyko multipleksowania. Czas pokaże :)Odpowiedź brzmi nie. Cel między nimi jest bardzo różny. Istnieje nawet RFC dla WebSocket przez HTTP / 2, który pozwala na tworzenie wielu połączeń WebSocket za pomocą pojedynczego potoku HTTP / HTTP.
WS przez HTTP / 2 będzie grą oszczędzającą zasoby, skracając czas otwierania nowych połączeń i pozwalając na więcej kanałów komunikacji bez dodatkowego kosztu większej liczby gniazd, miękkich przerw IRQ i buforów.
https://tools.ietf.org/html/draft-hirano-httpbis-websocket-over-http2-01
źródło
Cytując ten artykuł InfoQ :
W ten sposób push HTTP2 jest naprawdę czymś pomiędzy twoją przeglądarką a serwerem, podczas gdy Websockets naprawdę ujawniają interfejsy API, które mogą być używane zarówno przez klienta (javascript, jeśli działa w przeglądarce), jak i kod aplikacji (uruchomiony na serwerze) do przesyłania danych w czasie rzeczywistym.
źródło
Wymiana wiadomości i proste przesyłanie strumieniowe (nie audio, wideo) może odbywać się zarówno przez multipleksowanie HTTP / 2, jak i WebSockets. Więc niektóre nakładają się, ale WebSockets mają dobrze ustalony protokół, wiele frameworków / API i mniej nagłówków. Oto fajny artykuł na ten temat .
źródło
Będzie implementacja WebSocket w HTTP / 2. https://tools.ietf.org/html/rfc8441
źródło
Na razie kwiecień 2020 r. Protokół HTTP / 2 nie powoduje, że WebSockets stają się przestarzałe. Największą zaletą WebSockets nad HTTP2 jest to
Oznacza, że HTTP / 2 nie oferuje żadnego interfejsu API JS, takiego jak WebSockets, umożliwiającego komunikację i transfer pewnego rodzaju JSON lub innych danych na serwer bezpośrednio z aplikacji (np. Strony internetowej). Tak więc, o ile uważam, HTTP / 2 sprawi, że WebSockets stanie się przestarzałe, jeśli zacznie oferować API takie jak WebSockets do komunikacji z serwerem. Do tego czasu jest to tylko zaktualizowana i szybsza wersja HTTP 1.1.
źródło
Na dzień dzisiejszy nie.
HTTP / 2, w porównaniu do HTTP, pozwala na utrzymanie połączenia z serwerem. Stamtąd możesz mieć wiele strumieni danych jednocześnie. Chodzi o to, że możesz pchać wiele rzeczy jednocześnie, nawet bez żądania klienta. Na przykład, gdy przeglądarka prosi o
index.html
, serwer może chcieć również nacisnąćindex.css
iindex.js
. Przeglądarka nie poprosiła o to, ale serwer może to zrobić bez pytania, ponieważ może założyć, że będziesz chciał za kilka sekund.Jest to szybciej niż HTTP / 1 alternatywę uzyskiwania
index.html
, analizowania go, odkrywając to potrzebujeindex.js
iindex.css
, a następnie blok 2 inne wnioski o tych plikach. HTTP / 2 pozwala serwerowi przesyłać dane, o które klient nawet nie prosił.W tym kontekście jest podobny do WebSocket, ale nie jest tak naprawdę z założenia. WebSocket powinien umożliwiać dwukierunkową komunikację podobną do połączenia TCP lub połączenia szeregowego. To gniazdo, w którym oboje komunikują się ze sobą. Główna różnica polega także na tym, że można wysyłać dowolne pakiety danych w nieprzetworzonych bajtach, a nie w postaci protokołu HTTP. Pojęcia nagłówków, ścieżek i ciągów zapytań występują tylko podczas uzgadniania, ale WebSocket otwiera strumień danych.
Inną różnicą jest to, że uzyskujesz o wiele bardziej precyzyjny dostęp do WebSocket w JavaScript, podczas gdy w przypadku HTTP jest on obsługiwany przez przeglądarkę. Wszystko, co zyskujesz dzięki HTTP, to wszystko, co możesz zmieścić w
XHR
/fetch()
. Oznacza to również, przeglądarka będzie dostać się przechwycić i zmodyfikować nagłówki HTTP bez ciebie jest w stanie go kontrolować (npOrigin
,Cookies
itp). Ponadto to, co HTTP / 2 jest w stanie wypchnąć, jest wysyłane do przeglądarki. Oznacza to, że JS nie zawsze (jeśli w ogóle) wie, że wszystko jest popychane. Ponownie, ma to sensindex.css
iindex.js
ponieważ przeglądarka go buforuje, ale nie tyle pakietów danych.To naprawdę wszystko w nazwie. HTTP oznacza HyperText Transfer Protocol. Koncentrujemy się na koncepcji przenoszenia aktywów. WebSocket polega na budowaniu połączenia przez gniazdo, w którym dane binarne są przekazywane dwukierunkowo.
Tym, o którym tak naprawdę nie rozmawiamy, jest SSE (zdarzenia wysyłane przez serwer). Przekazywanie danych do aplikacji (JS) nie jest intencją HTTP / 2, ale dotyczy SSE. SSE zostaje naprawdę wzmocnione dzięki HTTP / 2. Ale nie jest to prawdziwy zamiennik dla WebSockets, gdy ważne są same dane, a nie osiągane zmienne punkty końcowe. Dla każdego punktu końcowego w WebSocket tworzony jest nowy strumień danych, ale w SSE jest on dzielony między już istniejącą sesją HTTP / 2.
Podsumowano tutaj cele dla każdego:
źródło