HTTP / 2プロトコルについて学習しています。これは、小さなメッセージフレームを持つバイナリプロトコルです。単一のTCP接続を介したストリーム多重化を可能にします。概念的には、WebSocketに非常によく似ています。
廃止されたWebソケットを、ヘッダーのないHTTP / 2リクエストやサーバー起動のプッシュメッセージに置き換える計画はありますか?それともWebSocketはHTTP / 2を補完するのでしょうか?
HTTP / 2プロトコルについて学習しています。これは、小さなメッセージフレームを持つバイナリプロトコルです。単一のTCP接続を介したストリーム多重化を可能にします。概念的には、WebSocketに非常によく似ています。
廃止されたWebソケットを、ヘッダーのないHTTP / 2リクエストやサーバー起動のプッシュメッセージに置き換える計画はありますか?それともWebSocketはHTTP / 2を補完するのでしょうか?
回答:
私が理解したことから、HTTP / 2はwebsocketの代わりではなく、SPDYプロトコルの標準化を目指しています。
HTTP / 2では、サーバープッシュが舞台裏で使用され、クライアントがブラウザからリソースをロードするのを改善しています。開発者は、開発中にそれを気にする必要はありません。ただし、Websocketを使用すると、開発者は独自の全二重接続でメッセージを消費およびプッシュできるAPIを使用できます。
これらは同じものではなく、互いに補完し合う必要があります。
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を実現する実際の例を含む良い記事です。
私はネーと言います(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コンテナの動作方法に影響します。
ssh
、ブラウザにターミナルを実装することは、Websocketを使用するときに簡単です。特に複数のタブが開いている場合は、HTTP / 2で頭痛の種になるでしょう。また、ブラウザ(またはHTTP / 2プロキシの1つ)が接続を閉じた場合はどうなりますか?クライアントは、新しいデータが利用できないことを想定できますか?投票に戻ります。
onclose
コールバックをサポートしているため、ポーリングは必要ありません。多重化に関しては、選択というよりむしろ必要だったと思います。keep-alive
失敗し、「最初の」パフォーマンスへの影響を回避する唯一の方法は、多重化のリスクを冒すことでした。時間は教えてくれます:)
答えはいいえだ。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
さて、このInfoQ記事から引用するには:
さて、答えは単純な理由で明らかにノーです:上記で見たように、HTTP / 2はサーバーがクライアントキャッシュに積極的にリソースを送信できるようにするサーバープッシュを導入します。ただし、クライアントアプリケーション自体にデータをプッシュすることはできません。サーバープッシュはブラウザによってのみ処理され、アプリケーションコードにポップアップしません。つまり、アプリケーションがこれらのイベントの通知を取得するためのAPIはありません。
そして、HTTP2プッシュは実際にはブラウザーとサーバーの間の何かですが、Websocketは、リアルタイムデータを転送するためにクライアント(ブラウザーで実行されている場合はJavaScript)とアプリケーションコード(サーバーで実行)の両方で使用できるAPIを実際に公開します。
メッセージ交換と単純なストリーミング(オーディオ、ビデオストリーミングではない)は、Http / 2多重化とWebSocketの両方を介して実行できます。そのため、いくつかのオーバーラップがありますが、WebSocketには十分に確立されたプロトコル、多くのフレームワーク/ APIがあり、ヘッダーのオーバーヘッドが少なくなっています。 ここにトピックに関する素晴らしい記事があります。
HTTP / 2にはWebSocket実装があります。 https://tools.ietf.org/html/rfc8441
現時点では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の更新された高速バージョンです。
今日、いいえ。
HTTP / 2は、HTTPと比較して、サーバーとの接続を維持できます。そこから、複数のデータストリームを同時に使用できます。その意図は、クライアントが要求しなくても、同時に複数のものをプッシュできることです。ブラウザが要求すると、例えばindex.html
、サーバーは、プッシュするかもしれませんindex.css
とindex.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ヘッダに取得することを意味しOrigin
、Cookies
など)。また、HTTP / 2がプッシュできるものはブラウザに送信されます。つまり、JSは常に(あるとしても)プッシュされていることを認識しているわけではありません。繰り返しになりますがindex.css
、index.js
これはブラウザがキャッシュするので意味がありますが、データパケットではそれほどではありません。
名前のとおりです。HTTPはHyperText Transfer Protocolの略です。私たちは、資産を譲渡するという概念に重点を置いています。WebSocketは、バイナリデータが双方向に渡されるソケット接続を構築するためのものです。
私たちが実際に議論していないのはSSE(サーバー送信イベント)です。アプリケーション(JS)へのデータのプッシュは、HTTP / 2の意図ではありませんが、SSE向けです。SSEはHTTP / 2で本当に強化されています。しかし、重要なのは、到達する変数のエンドポイントではなく、データ自体である場合、WebSocketの実際の置き換えではありません。WebSocketを使用する各エンドポイントに対して新しいデータストリームが作成されますが、SSEを使用すると、既存のHTTP / 2セッション間で共有されます。
ここに要約すると、それぞれの目的があります。