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 :
„Strumień” to niezależna, dwukierunkowa sekwencja ramek wymienianych między klientem a serwerem w ramach połączenia HTTP / 2. Strumienie mają kilka ważnych cech:
Pojedyncze połączenie HTTP / 2 może zawierać wiele jednocześnie otwartych strumieni, z ramkami przeplatającymi punkty końcowe z wielu strumieni.
Strumienie mogą być ustanawiane i używane jednostronnie lub współdzielone przez klienta lub serwer.
Strumienie mogą być zamykane przez dowolny punkt końcowy.
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
Protokół ma być rozszerzalny; przyszłe wersje prawdopodobnie wprowadzą dodatkowe koncepcje, takie jak multipleksowanie.
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.