HTTP / 2はWebSocketを廃止しますか?


268

HTTP / 2プロトコルについて学習しています。これは、小さなメッセージフレームを持つバイナリプロトコルです。単一のTCP接続を介したストリーム多重化を可能にします。概念的には、WebSocketに非常によく似ています。

廃止されたWebソケットを、ヘッダーのないHTTP / 2リクエストやサーバー起動のプッシュメッセージに置き換える計画はありますか?それともWebSocketはHTTP / 2を補完するのでしょうか?


受け入れられた答えは正しいと思います。WebSocketは、Webアプリケーションがサーバープッシュメッセージを含む双方向でサーバーと通信するための好ましいソリューションです。HTTPはブラウザだけでなく、クライアントとサーバーの両方が低レベルのAPIを使用できる場合に使用され、Webソケットは必要ありません。それでも、ほとんどの人はWebアプリケーションにHTTPを使用しており、JavaScriptに公開されたAPIに関心があります。承認された回答が異なるはずであるとモデレーターが考える場合、この質問は明らかに多くの見解を生み出し、私の意見は間違っているかもしれないので、私はそれに反対しません。
vbezhenar

回答:


162

私が理解したことから、HTTP / 2はwebsocketの代わりではなく、SPDYプロトコルの標準化を目指しています。

HTTP / 2では、サーバープッシュが舞台裏で使用され、クライアントがブラウザからリソースをロードするのを改善しています。開発者は、開発中にそれを気にする必要はありません。ただし、Websocketを使用すると、開発者は独自の全二重接続でメッセージを消費およびプッシュできるAPIを使用できます。

これらは同じものではなく、互いに補完し合う必要があります。


3
ギローム、回答ありがとうございます。しかし、私はあなた(または誰か)がHTTP / 2仕様から参照を追加できるかどうか疑問に思っています。私はブログなどから読んだもの-HTTP / 2では真の双方向通信がありますか?
Martin Meeser、2015年

3
HTTP / 2仕様がHTTP / 2の起源とそれがWebSocketとどのように異なるかについての詳細を説明するのに適切な場所であるかどうかはわかりません。ただし、HTTP / 2では双方向通信を使用していることを簡単に確認できます。goo.gl / IJVxWS(ページ6および13)
Guillaume D.

27
HTTP / 2は確かに双方向ですが、対称ではありません。つまり、クライアントだけが適切な要求を送信でき、サーバーは応答と要求プロミス(プッシュ)を送信できます。これにより、送受信が許可されているものに関して双方がより「同等」であるという意味で、WebSocketは異なります。
ジョージアントニアディス

3
IEEEのソフトウェアエンジニアリングラジオには、HTTP2の起源に関する優れたポッドキャストがあります。私はこれだと思います:se-radio.net/2015/07/episode-232-mark-nottingham-on-http2
Max Murphy

2
完全な理論的根拠を持つ同様の答えは、こちらのInfoQ記事にあります。infoq.com
articles

151

HTTP / 2仕様を読み終えた後、HTTP / 2はほとんどのユースケースで廃止されたWebソケットを実行すると思いますが、すべてではないかもしれません。

PUSH_PROMISE(通称サーバープッシュ)はここでは問題になりません。これは単なるパフォーマンスの最適化です。

ブラウザでのWebSocketの主な使用例は、データの双方向ストリーミングを有効にすることです。したがって、OPの問題は、HTTP / 2がブラウザーで双方向ストリーミングを有効にするより良い仕事をするかどうかになると思います。そうだと思います。

まず第一に、それはある双方向ジ。ストリームセクションの紹介を読んでください:

「ストリーム」は、HTTP / 2接続内でクライアントとサーバー間で交換される独立した双方向のフレームシーケンスです。ストリームにはいくつかの重要な特性があります。

単一のHTTP / 2接続には、複数のストリームからのいずれかのエンドポイントインターリーブフレームを使用して、同時に開いている複数のストリームを含めることができます。

ストリームは、一方的に確立して使用するか、クライアントまたはサーバーで共有できます。

ストリームはどちらのエンドポイントでも閉じることができます。

このような記事(別の回答でリンクされています)は、HTTP / 2のこの側面について間違っています。彼らはそれが双方向ではないと言います。HTTP / 2では起こりえないことが1つあります。接続が開かれた後、サーバーは通常のストリームを開始できず、プッシュストリームのみを開始できます。しかし、クライアントがリクエストを送信してストリームを開くと、両側がいつでも永続的なソケットを介してDATAフレームを送信できます-完全な双方向。

これはWebSocketと大差ありません。サーバーもデータを送信する前に、クライアントはWebSocketアップグレードリクエストを開始する必要があります。

最大の違いは、WebSocketとは異なり、HTTP / 2は独自の多重化セマンティクスを定義することです。つまり、ストリームが識別子を取得する方法と、フレームがストリームのIDを伝達する方法です。HTTP / 2は、ストリームに優先順位を付けるためのフロー制御セマンティクスも定義します。これは、bidiのほとんどの実際のアプリケーションで重要です。

(この間違った記事には、Websocket標準に多重化があるとあります。いいえ、ありません。それを見つけるのはそれほど難しくありません。WebsocketRFC 6455を開き、open -Fを押して、「multiplex」と入力してください。

プロトコルは拡張可能であることを目的としています。将来のバージョンでは、多重化などの追加の概念が導入される可能性があります。

Websocketの多重化のための2013年のドラフト拡張があることがわかります。しかし、どのブラウザがそれをサポートしているかはわかりません。私はその拡張機能の裏側でSPA Webアプリケーションを構築しようとはしません。特にHTTP / 2が来ると、サポートが届かない可能性があります)。

多重化とは、たとえば、反応的に更新する単一ページのアプリを強化するために、bidiのWebSocketを開くたびに通常は自分で行う必要があることです。それがHTTP / 2仕様にあることをうれしく思います。

HTTP / 2でできることを知りたい場合は、gRPCをご覧ください。gRPCはHTTP / 2全体に実装されています。特に、gRPCが提供する半二重および全二重ストリーミングオプションに注目してください。(gRPCは現在ブラウザーでは機能しませんが、実際にはブラウザーが(1)HTTP / 2フレームをクライアントのJavaScriptに公開しておらず、(2)で使用されるTrailersを一般的にサポートしていないためですgRPC仕様。)

WebSocketにはまだ場所があるのでしょうか?大きなものは、サーバーからブラウザにプッシュされたバイナリデータです。HTTP / 2では、サーバーからブラウザーにプッシュされたバイナリデータは許可されますが、ブラウザーのJSでは公開されません。オーディオフレームやビデオフレームのプッシュなどのアプリケーションでは、これがWebSocketを使用する理由です。

編集:2020年1月17日

時間の経過とともに、この回答は徐々に上位に上がっています(この回答は多かれ少なかれ正しいため、これは良いことです)。ただし、通常はPUSH_PROMISEメッセージ指向のサーバー->クライアントプッシュをシングルページアプリで実際に使用する方法についての混乱や方法に関連するさまざまな理由で正しくないというコメントが時折あります。また、サーバープッシュバイナリデータであるブラウザーのWebSocketのユースケースがあります。JSONを含むテキストデータの場合は、WebSocketを使用せず、SSEを使用してください。

要約すると、HTTP / 2プロトコルは完全な双方向です。ただし、最新のウェブブラウザはフレーム指向のHTTP / 2プロトコルをJavaScriptに公開していません。とはいえ、HTTP / 2接続を介して同じオリジンに複数のリクエストを行うと、内部ではすべてのトラフィックが1つの接続で多重化されます(これが重要です!)。

したがって、リアルタイムチャットアプリを構築する必要がある場合、たとえば、オープンコネクションを持つチャットルーム内のすべてのクライアントに新しいチャットメッセージをブロードキャストする必要がある場合、Webソケットなしでこれを行うことができます(おそらくそうする必要があります)。

サーバー送信イベントを使用してメッセージをプッシュダウンし、フェッチ APIを使用してリクエストを送信します。サーバー送信イベント(SSE)はあまり知られていないがよくサポートされている APIであり、メッセージ指向のサーバーからクライアントへのストリームを公開します。クライアントのJavaScriptのようには見えませんが、内部的には、ブラウザー(HTTP / 2をサポートしている場合)は単一のTCP接続を再利用して、これらのメッセージをすべて多重化します。効率の低下はなく、実際にはWebSocketよりも優れています。複数のストリームが必要ですか?複数のイベントソースを開きます!これらは自動的に多重化されます。

サーバーソケットイベントは、Webソケットハンドシェイクよりもリソース効率が高く、初期遅延が少ないだけでなく、自動的にフォールバックしてHTTP / 1.1で動作するという優れた特性を備えています。しかし、HTTP / 2接続がある場合、それらは信じられないほどうまく機能します。

これは、反応的に更新するSPAを実現する実際の例を含む良い記事です。


21
この回答は、承認されたものを含め、他の回答と部分的に一致していません。また、直接的な情報源に基づいているため、最良の回答でもあります。
sudo

7
私はこの回答とコメントに完全に同意します。HTTP / 2はストリームベースの双方向です。
Martin Meeser

3
実際に正しい答え、男はソースと実世界のアプリケーション(grpc)をチェックするのに苦労しました
Vladimir Akopyan

1
WebSocketでは、クライアントがWebSocketアップグレードリクエストを開始するまで、サーバーは任意のバイトのプッシュを開始できませんが、その後はいつでもプッシュできます。HTTP / 2では、サーバーはクライアントがデータ接続を開始するまでバイトのプッシュを開始できませんが、その後いつでもバイトをプッシュできます。機能の違いは何ですか?私が指摘したように、PUSH_PROMISE機能はレッドニシンです。HTTP / 2がWebソケットの代わりになる理由ではありません。これは、ちょっとしたパフォーマンス最適化です。これは、HTTP / 2の中心、つまり双方向ストリーミングとは関係ありません。
masonk

1
この答えは単に間違っています。それは非常に多くの面を混乱させ、それは簡単に混乱します。ただし、問題の核心は、「bidi」HTTP / 2ストリームが要求/応答駆動型(かつ数に制限がある)であるのに対し、WebSocketsプロトコルは真のメッセージベースのBidiプロトコルです(要求/応答ベースではありません)。ハンドシェイクフェーズを除く)。これは、仕様を誤って読むだけでは解決できない大きな違いです(@masonkが誤って行ったように見えるため)。
ミスト

65

私はネーと言います(WebSocketは廃止されていません)。

最初に、そして最も頻繁に無視される問題は、HTTP / 2プッシュが強制可能ではなく、プロキシ、ルーター、他の仲介者、またはブラウザによってさえ無視される可能性があることです。

つまり(HTTP2ドラフトから):

仲介者はサーバーからプッシュを受信し、それらをクライアントに転送しないことを選択できます。つまり、プッシュされた情報をどのように利用するかは、仲介者次第です。同様に、仲介者は、サーバーによるアクションなしで、クライアントに追加のプッシュを行うことを選択できます。

したがって、HTTP / 2プッシュはWebSocketを置き換えることはできません。

また、HTTP / 2接続はしばらくすると閉じます。

規格が次のように述べていることは事実です:

HTTP / 2接続は永続的です。最高のパフォーマンスを得るには、サーバーとの通信が不要であると判断されるまで(たとえば、ユーザーが特定のWebページから移動したとき)、またはサーバーが接続を閉じるまで、クライアントは接続を閉じないことが予想されます。

だが...

サーバーは可能な限り開いた接続を維持することが推奨されますが、必要に応じてアイドル接続を終了することが許可されます。いずれかのエンドポイントがトランスポート層のTCP接続を閉じることを選択した場合、終端のエンドポイントは最初にGOAWAY(セクション6.8)フレームを送信する必要があります。これにより、両方のエンドポイントは、以前に送信されたフレームが処理されているかどうかを確実に判断し、必要な残りのタスクを適切に完了または終了できます。

同じ接続が開いている間にコンテンツをプッシュすることができ、HTTP / 2がHTTP / 1.1の「キープアライブ」によって導入されたパフォーマンスの問題のいくつかを解決したとしても... HTTP / 2接続は無期限に開いたままにはなりません。

また、閉じられたWebページがHTTP / 2接続を再開することもできません(長い引き戻しに戻らない限り)。

編集(2017年、2年後)

HTTP / 2の実装は、複数のブラウザタブ/ウィンドウが単一のHTTP / 2接続を共有pushすることを示します。つまり、それがどのタブ/ウィンドウに属しているのかわからないpushため、WebSocketの代わりとしてを使用する必要がなくなります。

編集(2020)

なぜ人々が回答に反対票を投じ始めたかはわかりません。どちらかといえば、回答が最初に投稿されてからの年月は、HTTP / 2がWebSocketを置き換えることができず、そのように設計されていないことを証明しました。

確かに、HTTP / 2に使用されるかもしれないトンネルのWebSocketコネクションが、これらのトンネリング接続がまだのWebSocketプロトコルが必要になりますし、彼らはHTTP / 2コンテナの動作方法に影響します。


4
WSソケットも永久に開いたままになることはありません。違いはストリームです。HTTP / 2は複数のストリームフローを提供します。つまり、サーバー上のフロー制御は非常に異なり、多くの場合ロックレスです。WS(プロトコルとして)は、規制されていない受信処理を備えている必要があります。フロー制御はスタックの上位に実装されています。セキュリティとサーバーの整合性のために、HTTP / 2はWSよりもはるかに優れています。
債券

4
@ bond、HTTP / 2にはトランスポート層として多くの利点があることに同意します(単一の接続を多数のブラウザータブで共有することは、ほんの一例です)。ただし、通信層としては設計されていません。それは機能的な質問です。どちらのプロトコルも異なるニーズに応えます。つまりssh、ブラウザにターミナルを実装することは、Websocketを使用するときに簡単です。特に複数のタブが開いている場合は、HTTP / 2で頭痛の種になるでしょう。また、ブラウザ(またはHTTP / 2プロキシの1つ)が接続を閉じた場合はどうなりますか?クライアントは、新しいデータが利用できないことを想定できますか?投票に戻ります。
Myst

1
ブラウザは、WS接続を簡単に閉じることができます。それは、あらゆる種類のネットワークのある生活です。正直なところ、HTTP / 2の多重化はやりすぎです。プロトコルは本当にそれを必要としませんでした。複数のストリームを開くと、TCPバッファーがスループットを制限する問題が発生し始めます。WSはHTTP / 2よりも機能が優れていることに同意します。基本的に、WSは、ユーザーが悪いことをするのを防ぐために多くの上位レベルの制御を必要とするものです。
2016年

2
ベンおじさん(スパイダーマン)を引用すると、「覚えておいてください。大きな力には大きな責任が伴います」。はい、@ボンド、あなたはとても正しいです。WebSocketは非常に「生の」プロトコルであるため、より責任のあるサーバー設計が必要です。そして、はい、WSはHTTP / 2と同じくらい簡単に閉じることができますが、WSはoncloseコールバックをサポートしているため、ポーリングは必要ありません。多重化に関しては、選択というよりむしろ必要だったと思います。keep-alive失敗し、「最初の」パフォーマンスへの影響を回避する唯一の方法は、多重化のリスクを冒すことでした。時間は教えてくれます:)
Myst

1
サーバー設計の観点から見ると、アウトバウンド多重化は複雑で費用のかかる問題です。内部的にポーリングするIOメカニズムが必要ですが、これは地獄のように高価です。大きなドキュメントをストリーミングしない限り、2番目のイベントが使用可能になり、多重化の実行に失敗する前に、リクエストがおそらく完全に内部的に応答してバッファリングされるため、多重化は機能しません。RTMPにはアウトバウンド多重化がありますが、それを行うのはAdobeのサーバーだけです。HTTP / 2がRTMPにどれほど近いかは驚くべきことです。
債券

39

答えはいいえだ。2つの目標は大きく異なります。単一のHTTP / 2 TCPパイプを介して複数のWebSocket接続を確立できるようにするHTTP / 2上のWebSocketのRFCもあります。

HTTP / 2を介したWSは、新しい接続を開く時間を短縮し、ソケット、ソフトIRQ、およびバッファーを追加することなく、より多くの通信チャネルを可能にすることで、リソースを節約します。

https://tools.ietf.org/html/draft-hirano-httpbis-websocket-over-http2-01


すごい!これを実装したJavascriptクライアントの公開例はありますか?例が見つかりません。何をする必要がありますか?これは良いリソースですか?undertow.io/blog/2015/04/27/An-in-depth-overview-of-HTTP2.html
RaisinBranCrunch

1)ヘッダーの長さを見つける、2)フィールド名を小文字にする、という上記の主張の出典を知っている人はいますか?
Pim Heijden

@PimHeijdenがHTTP / 1.xでヘッダー長を検出するには、4バイトのエンドマーカーを探すためにすべてのバイトをループする必要があります。それは非常に高価です。フィールド名の大文字小文字の区別がないということは、大文字と小文字の両方のバージョンの文字に対してフィールド照合を行う必要があることも意味します。これには、チェックのために文字セット全体の大文字と小文字の知識が必要です。2.xでは、小文字であると想定できます。
債券

@RaisinBranCrunch Javascriptからこれを制御することはできません。ブラウザはあなたのためにすべてを行います。
債券

@bond現在、HTTP / 2とNginx、およびproxy_passを使用してWebSocket接続をソケットサーバーに送信していますが、1人のユーザーがWebサイトで複数のタブを開いている場合、ソケットサーバーはそれを複数の接続として扱います。HTTP / 2が1つのTCPパイプを介して接続を多重化している場合、サーバーはそれを1つの接続として扱うと思います。これは間違っていますか?サーバーが余分な不要な接続を行っていないことを確認する方法はありますか?
RaisinBranCrunch

23

さて、このInfoQ記事から引用するには:

さて、答えは単純な理由で明らかにノーです:上記で見たように、HTTP / 2はサーバーがクライアントキャッシュに積極的にリソースを送信できるようにするサーバープッシュを導入します。ただし、クライアントアプリケーション自体にデータをプッシュすることはできません。サーバープッシュはブラウザによってのみ処理され、アプリケーションコードにポップアップしません。つまり、アプリケーションがこれらのイベントの通知を取得するためのAPIはありません。

そして、HTTP2プッシュは実際にはブラウザーとサーバーの間の何かですが、Websocketは、リアルタイムデータを転送するためにクライアント(ブラウザーで実行されている場合はJavaScript)とアプリケーションコード(サーバーで実行)の両方で使用できるAPIを実際に公開します。


5

メッセージ交換と単純なストリーミング(オーディオ、ビデオストリーミングではない)は、Http / 2多重化とWebSocketの両方を介して実行できます。そのため、いくつかのオーバーラップがありますが、WebSocketには十分に確立されたプロトコル、多くのフレームワーク/ APIがあり、ヘッダーのオーバーヘッドが少なくなっています。 ここにトピックに関する素晴らしい記事があります


2

HTTP / 2にはWebSocket実装があります。 https://tools.ietf.org/html/rfc8441


いいえ、ありません... WebSocket接続はHTTP / 2を介してトンネリングされますが、HTTP / 2はプロトコルに取って代わることも、廃止されることもありません。
ミスト

@Myst言った?
Dzintars

2
いいえ、あなたはそれを言わなかった、私はしました。あなたは、HTTP / 2にWebSocket実装があると書いていますが、重要な詳細が省略されているため、IMHOは短すぎてやや誤解を招くように見えました。
ミスト

2

現時点では2020年4月、HTTP / 2によってWebSocketが廃止されることはありません。HTTP2を介したWebSocketの最大の利点は、

HTTP/2 works only on Browser Level not Application Level

HTTP / 2がWebSocketのようなJS APIを提供せず、通信を許可し、ある種のJSONまたはその他のデータをアプリケーション(例:ウェブサイト)から直接サーバーに転送することを意味します。したがって、私が信じている限り、HTTP / 2がWebSocketを廃止するのは、サーバーと通信するWebSocketのようなAPIを提供し始めた場合だけです。それまでは、HTTP 1.1の更新された高速バージョンです。


2

今日、いいえ。

HTTP / 2は、HTTPと比較して、サーバーとの接続を維持できます。そこから、複数のデータストリームを同時に使用できます。その意図は、クライアントが要求しなくても、同時に複数のものをプッシュできることです。ブラウザが要求すると、例えばindex.html、サーバーは、プッシュするかもしれませんindex.cssindex.js。ブラウザーはそれを要求しませんでしたが、サーバーは数秒で必要になると想定できるため、要求されずにそれを提供する場合があります。

これは、より速く得るためのHTTP / 1代替よりもindex.html、それを解析し、それが必要発見index.jsし、index.cssそしてその後、それらのファイルのための2つの他の要求を構築します。HTTP / 2を使用すると、サーバーはクライアントが要求していないデータもプッシュできます。

その意味では、それはWebSocketに似ていますが、実際には仕様ではありません。WebSocketは、TCP接続またはシリアル接続と同様の双方向通信を可能にすることになっています。これは、両方が互いに通信するソケットです。また、主な違いは、HTTPプロトコルにカプセル化されていない任意のデータパケットをrawバイトで送信できることです。ヘッダー、パス、クエリ文字列の概念はハンドシェイク中にのみ発生しますが、WebSocketはデータストリームを開きます。

もう1つの違いは、JavaScriptではWebSocketへのアクセスがはるかに微調整されるのに対し、HTTPではブラウザによって処理されることです。HTTPで取得できるのは、XHR/に収まるものすべてですfetch()。(:例えばそれはまた、ブラウザは、あなたがそれを制御できずに傍受し、変更HTTPヘッダに取得することを意味しOriginCookiesなど)。また、HTTP / 2がプッシュできるものはブラウザに送信されます。つまり、JSは常に(あるとしても)プッシュされていることを認識しているわけではありません。繰り返しになりますがindex.cssindex.jsこれはブラウザがキャッシュするので意味がありますが、データパケットではそれほどではありません。

名前のとおりです。HTTPはHyperText Transfer Protocolの略です。私たちは、資産を譲渡するという概念に重点を置いています。WebSocketは、バイナリデータが双方向に渡されるソケット接続を構築するためのものです。


私たちが実際に議論していないのはSSE(サーバー送信イベント)です。アプリケーション(JS)へのデータのプッシュは、HTTP / 2の意図ではありませんが、SSE向けです。SSEはHTTP / 2で本当に強化されています。しかし、重要なのは、到達する変数のエンドポイントではなく、データ自体である場合、WebSocketの実際の置き換えではありません。WebSocketを使用する各エンドポイントに対して新しいデータストリームが作成されますが、SSEを使用すると、既存のHTTP / 2セッション間で共有されます。


ここに要約すると、それぞれの目的があります。

  • HTTP-1つのアセットでリクエストに応答する
  • HTTP / 2-複数のアセットでリクエストに応答する
  • SSE-単方向テキスト(UTF-8)イベントストリームで応答する
  • WebSocket-双方向のバイナリデータストリームを作成する
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.