142

質問のタイトルのキーワードに関する SO や Web 上の多くの投稿を読み、それらから多くのことを学びました。私が読んだ質問の中には、特定の実装上の課題に関連するものもあれば、一般的な概念に焦点を当てたものもあります。すべての概念と、テクノロジー X がテクノロジー Y よりも発明された理由などを理解していることを確認したいだけです。だからここに行きます:

HTTP ポーリング:基本的に AJAX、XmlHttpRequest を使用します。

Http Long Polling: AJAX ですが、サーバーに更新がない限り、サーバーは応答を保持します。サーバーに更新があるとすぐにそれを送信し、クライアントは別の要求を送信できます。欠点は、追加のヘッダー データを送受信する必要があるため、追加のオーバーヘッドが発生することです。

HTTP ストリーミング:ロング ポーリングに似ていますが、サーバーは "Transfer Encoding: chunked" のヘッダーで応答するため、サーバーがデータを送信するたびに新しい要求を開始する必要はありません (したがって、追加のヘッダー オーバーヘッドを節約できます)。ここでの欠点は、サーバーから送信された複数のチャンクを区別するために、データの構造を「理解」して理解する必要があることです。

Java アプレット、Flash、Silverlight: TCP/IP 経由でソケット サーバーに接続する機能を提供しますが、これらはプラグインであるため、開発者はそれらに依存したくありません。

WebSockets:これらは、上記のメソッドの短所を次の方法で解決しようとする新しい API です。

  • Java アプレット、Flash、Silverlight などのプラグインに対する WebSocket の唯一の利点は、WebSocket がブラウザーにネイティブに組み込まれており、プラグインに依存しないことです。
  • HTTP ストリーミングに対する WebSocket の唯一の利点は、受信したデータを「理解」して解析する努力をする必要がないことです。
  • ロング ポーリングに対する WebSocket の唯一の利点は、余分なヘッダー サイズをなくすことと、リクエストのソケット接続を開いたり閉じたりできることです。

私が見逃している他の重要な違いはありますか? すでに SO にある多くの質問を 1 つの質問に再質問したり、組み合わせたりする場合は申し訳ありませんが、これらの概念に関して SO と Web にあるすべての情報から完全に理解したいと思います。

ありがとう!

4

4 に答える 4

108

あなたが特定したものよりも多くの違いがあります。

デュプレックス/指向性:

  • 単方向: HTTP ポーリング、ロング ポーリング、ストリーミング。
  • 双方向: WebSocket、プラグイン ネットワーキング

レイテンシーの増加順 (概算):

  • WebSocket
  • プラグインネットワーキング
  • HTTP ストリーミング
  • HTTP ロングポール
  • HTTP ポーリング

CORS (クロスオリジン サポート):

  • WebSocket: はい
  • プラグイン ネットワーキング: ポリシー リクエストによるフラッシュ (他については不明)
  • HTTP * (一部の最近のサポート)

ネイティブ バイナリ データ (型付き配列、ブロブ):

  • WebSocket: はい
  • プラグイン ネットワーキング: Flash を使用しない (ExternalInterface 全体で URL エンコードが必要)
  • HTTP *: バイナリ型のサポートを有効にする最近の提案

効率が低下する帯域幅:

  • プラグイン ネットワーキング: フラッシュ ソケットは、最初のポリシー リクエストを除いて raw です
  • WebSockets: 接続セットアップ ハンドシェイクとフレームあたり数バイト
  • HTTP ストリーミング (サーバー接続の再利用)
  • HTTP ロング ポール: すべてのメッセージの接続
  • HTTP ポーリング: すべてのメッセージの接続 + データ メッセージなし

モバイル デバイスのサポート:

  • WebSocket: iOS 4.2 以降。一部の Android では、Flash エミュレーションを介するか、Android用 Firefox または Android 用Google Chrome を使用します。どちらもネイティブの WebSocket サポートを提供します。
  • プラグイン ネットワーキング: 一部の Android。iOS にはありません
  • HTTP *: ほとんどはい

Javascript の使用の複雑さ (最も単純なものから最も複雑なものまで)。確かに、複雑さの尺度はやや主観的です。

  • WebSocket
  • HTTP ポーリング
  • プラグインネットワーキング
  • HTTP ロング ポール、ストリーミング

また、 Server-Sent Eventsと呼ばれる HTTP ストリーミングの標準化に関する W3C の提案があることにも注意してください。これは現在、進化のかなり初期段階にあり、WebSocket に匹敵するシンプルさを備えた標準 Javascript API を提供するように設計されています。

于 2012-09-23T20:57:25.277 に答える
14

多くの分野をカバーする他の人からのいくつかの素晴らしい回答。ここで少し補足です。

Java アプレット、Flash、Silverlight などのプラグインに対する WebSocket の唯一の利点は、WebSocket がブラウザーにネイティブに組み込まれており、プラグインに依存しないことです。

これが、Java アプレット、Flash、または Silverlight を使用してソケット接続を確立できるという意味であれば、可能です。ただし、制限があるため、現実の世界に展開されることはあまりありません。

たとえば、仲介者はそのトラフィックをシャットダウンすることができ、実際にシャットダウンします。WebSocket 標準は、既存の HTTP インフラストラクチャと互換性があるように設計されているため、ファイアウォールやプロキシなどの仲介者による干渉を受ける可能性がはるかに低くなります。

さらに、WebSocket は専用ポートを必要とせずにポート 80 と 443 を使用できます。これも、プロトコル設計が既存の HTTP インフラストラクチャと可能な限り互換性を持つようになっているためです。

これらの代替ソケット (Java、Flash、および Silverlight) は、クロスオリジン アーキテクチャで安全に使用することは困難です。したがって、クロスオリジンでそれらを使用しようとすることが多い人々は、それを安全に行う努力をするのではなく、不安を許容します.

また、追加の「非標準」ポートを開く必要がある場合 (管理者がやりたがらないこと) や、管理が必要なポリシー ファイルが必要になる場合もあります。

要するに、ソケット接続に Java、Flash、または Silverlight を使用することには十分な問題があるため、深刻なアーキテクチャに展開されることはあまりありません。Flash と Java には、おそらく少なくとも 10 年間はこの機能がありましたが、まだ普及していません。

WebSocket 標準は、これらの制限を念頭に置き、できればそこからいくつかの教訓を学び、新鮮なアプローチから始めることができました。

一部の WebSocket 実装では、WebSocket 接続を確立できない場合 (古いブラウザーで実行している場合や仲介者が干渉している場合など) に、フォールバックとして Flash (またはおそらく Silverlight や Java) を使用します。

これらの状況に対するある種のフォールバック戦略は賢明であり、必要でさえありますが、Flash などを使用するほとんどの人は上記の欠点に悩まされます。そうである必要はありません -- Flash、Silverlight などを使用してセキュアなクロスオリジン対応の接続を実現するための回避策があります -- しかし、ほとんどの実装ではそれが簡単ではないため行われません。

たとえば、クロスオリジン接続のために WebSocket に依存している場合、それは正常に機能します。しかし、その後、古いブラウザーで実行したり、ファイアウォール/プロキシが干渉したり、フォールバックとして Flash に依存したりすると、同じクロスオリジン接続を行うのが難しくなります。もちろん、セキュリティを気にしない限り。

つまり、かなりの作業を行うか、それをうまく行ったフレームワークを使用する準備ができていない限り、ネイティブ接続と非ネイティブ接続で機能する単一の統合アーキテクチャを持つことは困難です。理想的なアーキテクチャでは、接続がネイティブかどうかに気付かないでしょう。セキュリティ設定はどちらの場合でも機能します。クラスタリング設定は引き続き機能します。容量計画は引き続き有効です。等々。

HTTP ストリーミングに対する WebSocket の唯一の利点は、受信したデータを「理解」して解析する努力をする必要がないことです。

HTTP ストリームを開いて、数分、数時間、またはそれ以上データが流れるのをじっと待っているだけという単純なものではありません。クライアントが異なれば動作も異なり、それを管理する必要があります。たとえば、一部のクライアントはデータをバッファリングし、しきい値に達するまでアプリケーションに解放しません。さらに悪いことに、接続が閉じられるまでデータをアプリケーションに渡さないものもあります。

そのため、複数のメッセージをクライアントに送信している場合、たとえば 50 メッセージ分のデータが受信されるまで、クライアント アプリケーションがデータを受信しない可能性があります。それはあまりにもリアルタイムではありません。

HTTP ストリーミングは、WebSocket が利用できない場合の実行可能な代替手段になる可能性がありますが、万能薬ではありません。現実世界の条件で、Web の荒れ地で堅牢な方法で作業するには、十分な理解が必要です。

私が見逃している他の重要な違いはありますか?

まだ誰も言及していないことがもう1つありますので、それを取り上げます。

WebSocket プロトコルは、上位レベルのプロトコルのトランスポート層として設計されました。WebSocket 接続を介して直接 JSON メッセージなどを送信できますが、標準またはカスタム プロトコルを伝送することもできます。

たとえば、人々がすでに行っているように、WebSocket を介して AMQP または XMPP を実行できます。したがって、クライアントは、あたかもブローカー自体に直接接続されているかのように (場合によってはそうです)、AMQP ブローカーからメッセージを受信できます。

または、何らかのカスタム プロトコルを備えた既存のサーバーがある場合は、それを WebSocket 経由で転送して、そのバックエンド サーバーを Web に拡張できます。多くの場合、企業内でロックされている既存のアプリケーションは、バックエンド インフラストラクチャを変更することなく、WebSocket を使用して範囲を広げることができます。

(当然のことながら、これらすべてを安全に実行できるようにしたいので、ベンダーまたは WebSocket プロバイダーに確認してください。)

一部の人々は、WebSocket を Web 用の TCP と呼んでいます。TCP が高レベルのプロトコルを転送するのと同じように、WebSocket も転送しますが、Web インフラストラクチャと互換性のある方法で転送します。

そのため、WebSocket を介して直接 JSON (またはその他の) メッセージを送信することは常に可能ですが、既存のプロトコルも考慮する必要があります。やりたいことがたくさんあるので、それを実行するためにすでに考えられているプロトコルがおそらくあるからです。

すでに SO にある多くの質問を 1 つの質問に再質問したり、組み合わせたりする場合は申し訳ありませんが、これらの概念に関して SO と Web にあるすべての情報から完全に理解したいと思います。

これは素晴らしい質問でした。回答はすべて非常に有益でした。

于 2012-09-24T06:47:41.987 に答える
10

もう1つ質問すると、WebSocketがキャッシュされていないのに、httpストリーミングもプロキシによってキャッシュされる可能性があるという記事に出くわしました。どういう意味ですか?

(StackOverflowはコメント応答のサイズを制限するため、インラインではなくここで回答する必要がありました。)

それは良い点です。これを理解するために、従来のHTTPシナリオについて考えてみてください...ブラウザがWebページを開いたとすると、たとえばhttp://example.comを要求します。サーバーは、ページのHTMLを含むHTTPで応答します。次に、ブラウザはページにリソースがあることを確認するため、CSSファイル、JavaScriptファイル、および画像の要求を開始します。それらはすべて静的ファイルであり、それらを要求するすべてのクライアントで同じになります。

一部のプロキシは静的リソースをキャッシュするため、他のクライアントからの後続の要求は、中央のWebサーバーに戻って取得するのではなく、プロキシから静的リソースを取得できます。これはキャッシングであり、中央サービスからリクエストと処理をオフロードするための優れた戦略です。

したがって、クライアント#1はhttp://example.com/images/logo.gifを要求します。そのリクエストはプロキシを経由して、logo.gifを提供する中央のWebサーバーに到達します。logo.gifがプロキシを通過すると、プロキシはその画像を保存し、アドレスhttp://example.com/images/logo.gifに関連付けます。

クライアント#2がやって来て、http://example.com/images/logo.gifも要求すると、プロキシは画像を返すことができ、中央のWebサーバーに戻るための通信は必要ありません。これにより、エンドユーザーへの応答が速くなり、常に優れていますが、センターへの負荷が少なくなることも意味します。これは、ハードウェアコストの削減、ネットワークコストの削減などにつながる可能性があります。したがって、これは良いことです。

この問題は、logo.gifがWebサーバーで更新されるときに発生します。プロキシは、新しいイメージがあることを認識せずに、古いイメージを引き続き提供します。これにより、すべてが期限切れになり、プロキシが「期限切れ」になる前に短時間だけ画像をキャッシュし、次のリクエストがプロキシを経由してWebサーバーに送られ、プロキシのキャッシュが更新されます。中央サーバーが既知のキャッシュなどにプッシュできる、より高度なソリューションもあり、物事はかなり洗練されたものになる可能性があります。

これはあなたの質問とどのように結びついていますか?

サーバーがクライアントにHTTPをストリーミングしているHTTPストリーミングについて質問しました。ただし、ストリーミングHTTPは、データの送信を停止しないことを除けば、通常のHTTPと同じです。Webサーバーが画像を提供する場合、HTTPをクライアントに送信し、最終的に終了します。つまり、画像全体を送信したことになります。また、データを送信する場合もまったく同じですが、サーバーは非常に長い時間送信するだけであるか(たとえば、非常に巨大な画像のように)、終了することはありません。

プロキシの観点からは、イメージなどの静的リソースのHTTPと、HTTPストリーミングのデータを区別できません。どちらの場合も、クライアントはサーバーに要求を出しました。プロキシはその要求と応答も記憶していました。次にその要求が着信すると、プロキシは同じ応答を提供します。

したがって、クライアントが株価を要求し、応答を受け取った場合、次のクライアントが同じ要求を行い、キャッシュされたデータを取得する可能性があります。おそらくあなたが望むものではありません!株価をリクエストする場合は、最新のデータが必要ですよね?

だからそれは問題です。

そのような問題を処理するためのトリックと回避策があります、それは本当です。明らかに、HTTPストリーミングは現在使用されているため、機能させることができます。エンドユーザーにはすべて透過的ですが、これらのアーキテクチャを開発および保守する人々は、フープを飛び越えて代償を払わなければなりません。その結果、アーキテクチャが複雑になり、メンテナンス、ハードウェア、複雑さ、コストが増加します。また、開発者は、アプリケーション、GUI、およびビジネスロジックだけに集中する必要があるときに、必要のないことを気にする必要があることがよくあります。つまり、基盤となる通信について気にする必要はありません。

于 2012-09-24T16:26:33.097 に答える
4

HTTP はクライアントがサーバーと接続できる数を 2 に制限しており (ただし、これはサブドメインを使用することで軽減できます)、IE はこれを熱心に実施することが知られています。Firefox と Chrome ではさらに多くのことが許可されています (頭のてっぺんに正確にいくつあるかは覚えていませんが)。これは大きな問題のようには思えないかもしれませんが、リアルタイム更新のために常に 1 つの接続を使用している場合、他のすべての要求は他の HTTP 接続を介してボトルネックになる必要があります。また、クライアントからのオープン接続が増えると、サーバーにより多くの負荷がかかるという問題があります。

WebSocket は TCP ベースのプロトコルであるため、この HTTP レベルの接続制限の影響を受けません (ただし、もちろん、ブラウザーのサポートは均一ではありません)。

于 2012-09-23T19:20:23.900 に答える