Nachdem ich gerade mit dem Lesen der HTTP / 2-Spezifikation fertig bin, denke ich, dass HTTP / 2 für die meisten Anwendungsfälle veraltete Websockets enthält, aber möglicherweise nicht für alle.
PUSH_PROMISE
(umgangssprachlich als Server-Push bezeichnet) ist hier nicht das Problem. Das ist nur eine Leistungsoptimierung.
Der Hauptanwendungsfall für Websockets in einem Browser besteht darin, das bidirektionale Streaming von Daten zu ermöglichen. Ich denke also, die Frage des OP lautet, ob HTTP / 2 das bidirektionale Streaming im Browser besser ermöglicht, und ich denke, dass dies der Fall ist.
Zunächst einmal, es ist bi-di. Lesen Sie einfach die Einführung zum Abschnitt "Streams" :
Ein "Stream" ist eine unabhängige, bidirektionale Folge von Frames, die zwischen dem Client und dem Server innerhalb einer HTTP / 2-Verbindung ausgetauscht werden. Streams haben mehrere wichtige Eigenschaften:
Eine einzelne HTTP / 2-Verbindung kann mehrere gleichzeitig geöffnete Streams enthalten, wobei jeder Endpunkt Frames aus mehreren Streams verschachtelt.
Streams können einseitig eingerichtet und verwendet oder entweder vom Client oder vom Server gemeinsam genutzt werden.
Streams können von jedem Endpunkt geschlossen werden.
Artikel wie dieser (in einer anderen Antwort verlinkt) sind in Bezug auf diesen Aspekt von HTTP / 2 falsch. Sie sagen, es ist kein Bidi. Eines kann mit HTTP / 2 nicht passieren: Nach dem Öffnen der Verbindung kann der Server keinen regulären Stream initiieren, sondern nur einen Push-Stream. Sobald der Client einen Stream durch Senden einer Anfrage öffnet, können beide Seiten jederzeit DATA-Frames über einen dauerhaften Socket senden - volles Bidi.
Das unterscheidet sich nicht wesentlich von Websockets: Der Client muss eine Websocket-Upgrade-Anforderung initiieren, bevor der Server auch Daten senden kann.
Der größte Unterschied besteht darin, dass HTTP / 2 im Gegensatz zu Websockets eine eigene Multiplex-Semantik definiert: Wie Streams Bezeichner erhalten und wie Frames die ID des Streams tragen, auf dem sie sich befinden. HTTP / 2 definiert auch die Flusssteuerungssemantik zum Priorisieren von Streams. Dies ist in den meisten realen Anwendungen von Bidi wichtig.
(Dieser falsche Artikel besagt auch, dass der Websocket-Standard Multiplexing enthält. Nein, das ist nicht der Fall. Es ist nicht wirklich schwer, das herauszufinden. Öffnen Sie einfach den Websocket RFC 6455, drücken Sie ⌘-F und geben Sie "Multiplex" ein. Nachdem Sie gelesen haben
Das Protokoll soll erweiterbar sein. Zukünftige Versionen werden wahrscheinlich zusätzliche Konzepte wie Multiplexing einführen.
Sie werden feststellen, dass es 2013 eine Entwurfserweiterung für Websocket-Multiplexing gibt. Aber ich weiß nicht, welche Browser das unterstützen, wenn überhaupt. Ich würde nicht versuchen, meine SPA-Webanwendung auf der Rückseite dieser Erweiterung zu erstellen, insbesondere wenn HTTP / 2 kommt, wird der Support möglicherweise nie eintreffen.
Multiplexing ist genau das, was Sie normalerweise selbst tun müssen, wenn Sie einen Websocket für Bidi öffnen, um beispielsweise eine reaktiv aktualisierte App für einzelne Seiten zu betreiben. Ich bin froh, dass es in der HTTP / 2-Spezifikation enthalten ist und ein für alle Mal erledigt wurde.
Wenn Sie wissen möchten, was HTTP / 2 kann, schauen Sie sich einfach gRPC an. gRPC ist über HTTP / 2 implementiert. Schauen Sie sich speziell die Halb- und Vollduplex-Streaming-Optionen an, die gRPC bietet. (Beachten Sie, dass gRPC derzeit nicht in Browsern funktioniert. Dies liegt jedoch daran, dass die Browser (1) den HTTP / 2-Frame nicht dem Client-Javascript aussetzen und (2) im Allgemeinen keine Trailer unterstützen, die in verwendet werden die gRPC-Spezifikation.)
Wo könnten Websockets noch einen Platz haben? Das große Problem sind Server-> Browser-Push-Binärdaten. HTTP / 2 erlaubt zwar Server-> Browser-Push-Binärdaten, ist jedoch in Browser-JS nicht verfügbar. Für Anwendungen wie das Übertragen von Audio- und Videobildern ist dies ein Grund, Websockets zu verwenden.
Bearbeiten: 17. Januar 2020
Im Laufe der Zeit ist diese Antwort allmählich nach oben gestiegen (was gut ist, weil diese Antwort mehr oder weniger richtig ist). Es gibt jedoch immer noch gelegentliche Kommentare, die besagen, dass dies aus verschiedenen Gründen nicht korrekt ist, was normalerweise auf Verwirrung darüber zurückzuführen ist, PUSH_PROMISE
wie der nachrichtenorientierte Server -> Client-Push in einer App mit nur einer Seite tatsächlich verwendet werden soll. Und es gibt einen Anwendungsfall für Websockets in einem Browser, bei dem es sich um servergesteuerte Binärdaten handelt. Verwenden Sie für Textdaten einschließlich JSON keine Websockets, sondern SSE.
Um es noch einmal zusammenzufassen: Das HTTP / 2-Protokoll ist vollständig bi-di. Jedoch nicht den Rahmen orientierte HTTP / 2 - Protokoll zu JavaScript belichten moderne Web - Browser . Wenn Sie jedoch über eine HTTP / 2-Verbindung mehrere Anfragen an denselben Ursprung stellen, wird unter der Haube der gesamte Datenverkehr auf einer Verbindung gemultiplext (und das ist uns wichtig!).
Wenn Sie also eine Echtzeit-Chat-App erstellen müssen, beispielsweise wenn Sie neue Chat-Nachrichten an alle Clients im Chatroom senden müssen, die offene Verbindungen haben, können (und sollten) Sie dies ohne Websockets tun.
Sie würden Server-Sent Events verwenden, um Nachrichten nach unten zu drücken, und die Fetch- API, um Anforderungen nach oben zu senden. Server-Sent Events (SSE) ist eine wenig bekannte, aber gut unterstützte API, die einen nachrichtenorientierten Server-zu-Client-Stream verfügbar macht. Obwohl es für das Client-JavaScript nicht so aussieht, verwendet Ihr Browser (wenn er HTTP / 2 unterstützt) unter der Haube eine einzelne TCP-Verbindung wieder, um alle diese Nachrichten zu multiplexen. Es gibt keinen Effizienzverlust und tatsächlich ist es ein Gewinn gegenüber Websockets. Benötigen Sie mehrere Streams? Öffnen Sie mehrere EventSources! Sie werden automatisch für Sie gemultiplext.
Server-Sent Events sind nicht nur ressourceneffizienter und haben eine geringere anfängliche Latenz als ein Websocket-Handshake, sondern auch die nette Eigenschaft, dass sie automatisch zurückgreifen und über HTTP / 1.1 arbeiten. Aber wenn Sie eine HTTP / 2-Verbindung haben, funktionieren sie unglaublich gut.
Hier ist ein guter Artikel mit einem realen Beispiel für die Durchführung des reaktiv aktualisierten SPA.