Webプログラミングでポーリングが受け入れられるのはなぜですか?


108

現在、画像のリストを表示するRuby on Railsプロジェクトに取り組んでいます。

このプロジェクトの必需品は、Webページを更新する必要なく、リアルタイムで新しい投稿を表示することです。しばらく検索した後、PubNubなどのJavaScriptソリューションとサービスに出くわしました。ただし、提供されたソリューションはどれも意味がありません。

JavaScriptソリューション(ポーリング)では、次のことが起こります。

  • ユーザー1が写真のリストを表示します。
  • バックグラウンドでは、JavaScriptコードがエンドポイントを1秒ごとにポーリングして、新しい投稿があるかどうかを確認しています。
  • ユーザー2が新しい写真を追加します。
  • 新しいサイクルがトリガーされ、新しいデータを取得するまでに50ミリ秒の遅延があります。
  • 新しいコンテンツがDOMにロードされます

これは実世界の例に翻訳すると奇妙に思えます:

  • ユーザー1は、自分の机に写真の山を持っています。
  • 彼/彼女は毎秒カメラマンのところへ歩いて行き、彼が新しいものを持っているかどうか尋ねます。
  • 写真家は新しい写真を作成します。
  • 彼/彼女が中に入るとき、彼女は写真を撮り、それを山に置くことができます。

私の意見では、解決策は次のようにする必要があります:

  • ユーザー1は、自分の机に写真の山を持っています。
  • 写真家は新しい写真を撮ります。
  • 写真家は山まで歩いて、残りの部分と一緒に置きます。

PubNubソリューションは基本的に同じですが、今回はデータを共有するために当事者間でのインターンがあります。

言うまでもなく、両方のソリューションは、ロードするデータがない場合でもトリガーされるため、非常にエネルギーを消費します。

私の知る限り、ほとんどすべてのリアルタイムアプリケーションでこの実装方法が使用されている理由(論理)は説明されていません。


195
しばらくの間、Webブラウザは着信接続を受信できるサーバーではないことを無視します...待って、いや、それを無視しないでください。
GrandmasterB

17
@dennis:サーバーとクライアント間のステートフルで永続的な接続は、おそらくポーリングの必要性を取り除くでしょうが、それはWebの設計方法ではありません。
FrustratedWithFormsDesigner

58
Websocketsはどうですか?
I.devries 14

25
または、長いポーリングを見てください。基本的にはポーリングを行いますが、サーバーは新しいデータが表示されるまで応答しません。
Matsemann

53
コンピュータ空間には、完全に理にかなっている多くのソリューションとアルゴリズムがあり、それらはミートスペースで行うのはまったく馬鹿げています。
whatsisname

回答:


179

プッシュは、1人または限られた数のユーザーに適しています。

1人の写真家と1000人のユーザーが全員写真のコピーを必要とするシナリオを変更します。写真家は1000本の山まで歩かなければなりません。それらのいくつかは、ロックされたオフィスにあるか、床全体に広がっている可能性があります。または休暇中のユーザーで、現時点では新しい写真に興味がない。

写真家はいつも歩くのに忙しく、新しい写真を撮ることはありません。

基本的に:プル/ポールモデルは、リアルタイム要件が緩い多くの信頼性の低い読者に合わせて拡張できます(写真が山に到着するまでに10秒かかる場合、大したことです)。

とはいえ、プッシュモデルは多くの状況で優れています。低レイテンシが必要な場合(新しい写真が撮影されてから5秒後に必要)、または更新がまれであり、頻繁かつ予測可能なリクエストが必要な場合(写真家が1日に新しい写真を生成するときに10秒ごとに質問してください)、プルは不適切です。それはあなたが何をしようとしているかに依存します。ナスダック:プッシュ。気象サービス:プル。結婚式の写真家:おそらくプル。ニュース写真代理店:おそらくプッシュ。


32
1000人のユーザーとのアナロジーが大好きです。休暇中のものもあれば、興味のない人もいます。+1。
riwalk 14

4
@EsbenSkovPedersen:ソケット制限はIPアドレスによるものではありません。これは、開いているファイル記述子が最大であるためです。したがって、開いているソケットの最大数は、使用するIPアドレスの数に依存しません。
スリーブマン

10
これは、控えめに言ってもひどい類推です。プッシュが機能するためには、ユーザーのクライアントは何らかのオープン接続を維持する必要があります。実際、ポーリングは接続のエミュレーションです。一部のクライアントがポーリングしているため、すべてのクライアントに通知されるのは好きではありません。同様に、一部のクライアントがプッシュ通知のために接続を開くと、すべてのクライアントに通知されるわけではありません。これは、リソースをウィンドウの外に捨てることを勧める非常に悪いアドバイスです。1秒あたり10000リクエストで攻撃されることは、10000個のオープンソケットを維持することよりも、決して安くなることはありません
back2dos 14

8
@ptyx:1s間隔はここで議論されているものです。1秒あたり10kリクエストとは、10000個のTCPハンドシェイクと1万個のHTTPリクエスト(それぞれ2KBに到達しやすい)を意味します。これにより、サーバーのバックグラウンドノイズが何桁も大きくなります。ポーリングを導入するのと同じくらい簡単にプッシュサブスクリプションを作成する、さまざまなバトルテスト済みライブラリがあります。問題全体を完全に抽象化するmeteor.jsのようなフレームワークもあります。これ以上説明することなくスケーラビリティに訴えることも、議論の余地はほとんどありません。とにかく、私は自分の疑念を表明しており、議論を始めたくありません;)
back2dos 14

5
上記のback2dosのコメントに同意します。プルがプッシュよりも優れている場合、グーグル、スタック交換、フェイスブック、オンライン株式サービスなどはプル技術を使用します。しかし、そうではありません。基本的に、リスニングステーションをセットアップする代わりにサーバーを叩くと、非常に規模が大きくなります。主要なサービスはポーリングを避けます。
トラビスJ 14

106

WebSocketsについて言及しているのは1人だけだと本当に驚いています。サポートは基本的にすべての主要なブラウザに実装されています。

実際、PubNubはそれらを使用します。アプリケーションの場合、ブラウザはおそらく新しい写真が利用可能になるたびにブロードキャストするソケットをサブスクライブします。ソケットは写真を送信しませんが、ブラウザーが非同期でダウンロードできるようにリンクだけを送信します。

あなたの例では次のようなものを想像してください:

  1. ユーザーは、今後のすべての写真について知りたいことを写真家に知らせる
  2. 写真家は、スピーカーで新しい写真が利用可能であると言います
  3. ユーザーが写真家に写真を求めます

これは、元のサンプルソリューションに似ています。クライアントはサーバーにデータを送信する必要がないため、ポーリングよりも効率的です(ハートビートを除く)。

また、他の人が言及したように、古いブラウザで機能する単純なポーリングよりも優れた他の方法があります(ロングポーリングなど)。


43
@RobertHarveyどうしてWebSocketは質問に関係ないのですか?質問は、ポーリングが受け入れ可能な戦略であるかどうかを尋ねますが、最近では明らかに受け入れられない(または少なくとも最適ではない)ことを示しています。WebSocket、サーバー送信イベント、および長いポーリングは、事実上すべての単一のユースケースではるかに優れたパフォーマンスを発揮します。
ファブリシオマット14

7
@RobertHarveyそれは私の解釈であり、私が見る限り再構成はしていません。確かに、この質問は、なぜそれがまだ受け入れられており、最適な戦略ないのと尋ねましたが、これらはまだ密接に関連する私見です。
ファブリシオマット14

25
WebSockets(など)は、OPの「ソリューション」を実装するのに最も近いため、具体的に言及していなくても非常に関連性が高いと思います。
korylprince 14

6
言うまでもなく、StackExchange現在アクセスしているようなサイト(このWebページをキャッシュ/保存しているのを見ない限り)はを使用しますWebSockets。これが、@ korylprinceまで誰も言及しなかった理由も疑問に思っていた理由WebSocketsです。
トリシス14

6
@FabrícioMatté:実際には、すべての単一のユースケースではありません。長いポーリングでは、システムリソースを使用するすべてのユーザーに対してソケットを開いたままにする必要があります。時間的にそれほど重要ではないが、多くのユーザーがいるFrサービスは、ソケットを開いたままにしておくのが、短い304を時々処理するよりも通常高価です。ほとんどのサービスでは、わずかな遅延は問題になりません。通常、単一のマシンは、プッシュよりもポーリングでより多くのクライアントにサービスを提供できます。
ライライアン14

42

時には十分で十分です。

「リアルタイム」通信プロセスを実装するすべての可能な方法のうち、おそらくポーリングが最も簡単な方法です。ポーリング間隔が比較的長い場合(つまり、瞬時ではなく秒、分、または時間)、接続またはリソースのチェックによって消費されるクロックサイクルが実際に重要でない場合、ポーリングを効果的に使用できます。


3
これ、千倍。通常は十分であるため、受け入れられています。
corsiKa 14

1
それは十分に良い答えだ
ザインR

31

HTTPプロトコルは、クライアントが要求を開始するものでなければならないという点で制限されています。サーバーは、クライアントの要求に応答しない限り、クライアントと通信できません。

したがって、実際の例を調整するには、次の制限を追加します。

  • ユーザー2は、ユーザー1の質問に1文の返信でのみ応答でき、その後ユーザー1は退出する必要があります。ユーザー2には他の通信方法はありません。

この新しい抑制により、ポーリング以外でどのようにそれをしますか?


6
HTTP 2.0はサーバープッシュをサポートします。「プッシュにより、サーバーは明示的な要求を行うことなくクライアントに表現を送信できます。」en.wikipedia.org/wiki/HTTP_2.0
カプタン14

5
@kaptan、それは素晴らしいですが、利用できません。あなたが持っているもので間に合わせる。
リウォーク14

7
現在利用可能なロングポーリングもあり、プルを使用してプッシュモデルをシミュレートします。
ティムB 14

24
@dennis:産業用オートメーションソフトウェアを作成したので、センサーのポーリングの例についてコメントしたいだけです。ポーリングセンサーには2つの目的があります。最も明らかなのは、新しいデータを取得することです。それほど明らかではないのは、センサーがまだ生きており、バグによるクラッシュや工場火災による燃焼、または産業事故による融解ではないことを検出することです。沈黙、つまり返事がないという事実も貴重なデータです。
スリーブマン14

3
@dennisセンサーは、多くの場合、データに興味があるよりもずっと速く感知します。ポーリングを使用すると、気にしない更新であふれることなく、必要なときにセンサーの値を正確に取得できます。(アプリケーションがファイルを開いて読み取る必要があるのではなく、OSがファイルをディスク上のどこかで変更するたびにアプリケーションに通知した場合を想像してください)
immibis 14

13

ポーリングが受け入れられるのはなぜですか?実際には、すべてのソリューションは実際には低レベルのポーリングであるためです!

新しい画像が利用可能になり次第サーバーが更新する場合、通常はIPアドレスが頻繁に変更され、誰かがもう興味がないかどうかわからないため、クライアントは何らかの形でキープアライブ信号、たとえば、「まだここにいる、オフラインではない」

インターネットを介して送信できるデータパケットは1つだけなので、すべてのステートフル接続(TCP / IPなど)は同じように機能します。相手がまだそこにいるかどうかはわかりません。

したがって、すべてのプロトコルにはタイムアウトがあります。エンティティがX秒以内に応答しない場合、死んでいると推定されます。したがって、データを送信せずにサーバーとクライアントの間に開いている接続しかない場合でも、サーバーとクライアントは通常のキープアライブパケットを送信する必要があります(これらの接続を開いた場合、これは低レベルで処理されます)これは最終的にポーリングとは異なりますか?

したがって、おそらく最善のアプローチはロングポーリングです。

クライアントは、サイトをロードした直後にリクエストを送信します(たとえば、写真家に「新しい写真がある場合は教えてください」と伝えます)が、新しい写真がない場合、サーバーは応答しません。リクエストがタイムアウトするとすぐに、クライアントは再度尋ねます。

サーバーに新しい画像がある場合、新しい画像の列に並ぶすべてのクライアントにすぐに応答できます。したがって、クライアントはまだオープン接続で応答を待機しており、クライアントへの接続を確立する必要がないため、新しい写真を作成した後の反応時間はプッシュよりもさらに短くなります。また、クライアントからのポーリング要求は、クライアントとサーバー間の一定の接続よりもはるかに多くのトラフィックではありません!


すべてのソリューションが低レベルのポーリングになることに同意しません。データを送信するために必要なポーリングと、クライアントが失われたときを知るために必要なポーリングを混同しています。はい、後者は常にプロトコルスタックのどこかでポーリングを行いますが、非常に低い頻度(5分に1回など)である可能性がありますが、実際のデータを1秒ごとにポーリングするのは無駄であり、真のプッシュ通知では回避できますそれはスタックのどのレベルでもポーリングしていません。
アロングラネレク14

最初のキープアライブパケットはかなり高い頻度で実行されます。これは、一般的なタイムアウト間隔を避けたいため、TCP / IPで数秒は珍しくなく、tcpを使用しないほとんどすべてがファイアウォールによってブロックされる可能性があるためです。X秒ごとにデータパケットを送信する必要がある場合、実質的に無料でデータを入力してみませんか?
ファルコ14

1
@Guralnekの場合、キープアライブ間隔が5分の接続があったとしても、実際の遅延と失われたパケットを追加する必要があるため、タイムアウトは長くなります。最小限の帯域幅を節約しながら、クライアントが切断した後、サーバーが5分間多数の接続を維持しますので、全体的に、これはおそらくより多くのサーバリソースを要するだろう
ファルコ

1
長いポーリングの場合は+1。彗星en.wikipedia.org/wiki/Comet_%28programming%29
Zan Lynx 14年

9

ポーリングの利点の1つは、メッセージが欠落した場合や何かの状態がグリッチになった場合に発生する可能性のある害を制限することです。Xが5秒ごとにYの状態を要求すると、要求または応答が失われると、Xの情報は5ではなく10秒だけになります。Yがリブートされると、Xは次のことを知ることができます。時間YはXのメッセージの1つに応答できます。Xがリブートされた場合、その後Yに何かを尋ねることは決してないかもしれませんが、Xのステータスを監視している人は、Xがリブートされたことを認識するはずです。

XがYをポーリングする代わりに、XがYに依存してその状態が変化するたびに通知し、Yの状態が変化してメッセージをXに送信したが、何らかの理由でそのメッセージが受信されなかった場合、Xはその変化に気付かない可能性があります。同様に、Yがリブートされ、Xに何かに関するメッセージを送信する理由がない場合。

場合によっては、XがYに定期的にまたは変化したときにYがそのステータスをメッセージとして自律的に送信し、Yから何も聞かずに長すぎる場合にのみXポーリングを要求することが役立つ場合があります。そのような設計は、 Xがそのメッセージの大部分を送信する必要がある(通常、Xは少なくともメッセージの受信にまだ関心があることを少なくとも時々Yに通知する必要があり、Yは関心が示されずに長すぎる場合はメッセージの送信を停止する必要があります)。ただし、このような設計では、Yを永続的に使用する必要がありますXについての情報を維持し、それをポーリングした人に返信を送信し、それが誰であったかをすぐに忘れることはできません。Yが組み込みシステムである場合、このような単純化は、より小さくて安価なコントローラーを使用できるように、メモリ要件を十分に削減するのに役立ちます。

ポーリングは、信頼できない可能性のある通信媒体(UDPやラジオなど)を使用する場合に追加の利点があります。リンク層の確認応答の必要性を大幅に排除できます。XがステータスリクエストQをYに送信し、YがステータスレポートRで応答し、XがRを聞くと、XはQが受信したことを知るためにリンクレイヤーの肯定応答を聞く必要はありません。逆に、YがRを送信すると、Xがそれを受信したかどうかを知る必要も気にする必要もありません。Xがステータスリクエストを送信し、応答がない場合、別のリクエストを送信できます。Yがレポートを送信し、Xがそれを聞かない場合、Xは別のリクエストを送信します。各要求が1回送信され、応答が返されるか返されない場合、どちらの当事者も特定のメッセージが受信されたかどうかを知る必要も気にする必要もありません。確認応答を送信すると、ステータスリクエストまたはレポートとほぼ同じ帯域幅を消費する可能性があるため、要求レポートの往復を使用することは、非請求レポートおよび確認よりも多くの費用はかかりません。Xが応答を取得せずにいくつかのリクエストを送信する場合、一部の動的にルーティングされたネットワークでは、リンクレベルの確認を有効にする必要があります(そして、リクエストでYが同様に行うように要求します)。新しいルートですが、物事が機能している場合、リクエストレポートモデルはリンクレベルの承認を使用するよりも効率的です。


メッセージをXにプッシュするY(2番目の段落)で説明した問題は、各メッセージにシリアル番号を添付することで修正できます。メッセージが失われた場合、Xはそのシリアルを受信しなかったために認識します。その時点で、Yと同期するために他の手段を講じることができます。DNSマスター->スレーブ複製はこのように機能します。
korylprince

@korylprince:相手側が何かを送信する機会がある場合(および正常に送信した場合)、または相手側から何かを期待して受信しない理由がある場合、どちらの側も欠落しているメッセージを見つけることができます。一方がステータスの更新を送信し、確認を必要としないか、数回再試行した後に断念し、他方がスケジュールされた送信を予期していない場合、もう一方は接続が消えたことを知りません。
supercat 14

2
@korylprince-問題は、定期的なメッセージがなければ、Xが1日遅れ、1年遅れ、または10年遅れて欠落しているメッセージを検出する可能性があることです。妥当な時間内に欠落パケ​​ットを検出するには、何らかの方法でポーリングする必要があります。ポーリングを「プル」することも、ポーリングを「プッシュ」することもできます。最初は、第二は、「ハートビート」と呼ばれている「ポーリング」と呼ばれている
slebetman

両方とも非常に真実です。それはすべて状況に依存します。
korylprince 14

@slebetman:Yが再起動されます場合は定期的なメッセージがなければ、Xは、と思われることでメカニズムが存在しない場合が今までそれを発見。
supercat 14

1

問題は、不要なポーリングの量と不要なプッシュの量のバランスをとることです。

ポーリングする場合:

  • この瞬間に答えが得られます。たまにしか尋ねない場合や、この瞬間にデータセットが必要な場合に適しています。
  • 「コンテンツなし」という回答が返され、回線に無意味な負荷がかかる場合があります。
  • ポーリングするときだけ回線に負荷をかけますが、常にポーリングするときです。

プッシュした場合:

  • 回答が利用可能になったらすぐに配信するため、クライアント側ですぐに処理できます。
  • このデータに関心のないクライアントにデータを配信すると、回線に無意味な負荷がかかる可能性があります。
  • 新しいデータがあるたびに回線に負荷をかけますが、新しいデータがある場合のみです。

さまざまなシナリオとその短所に対処する方法には、たとえば、ポーリング間の最小時間、メインシステムから負荷を取り除くためのポーリングのみのプロキシ、または-プッシュの場合-登録して指定する規制など、いくつかのソリューションがあります必要なデータに続いて、ログオフ時に登録解除します。どちらが最適かは、一般的に言うことはできません。システムによって異なります。

あなたの例では、ポーリングは最も効率的なソリューションではありませんが、最も実用的なソリューションです。JavaScriptでポーリングシステムを作成するのは非常に簡単であり、配信側でもポーリングシステムを実装するのは非常に簡単です。画像データを配信するように作られたサーバーは、追加のリクエストを処理できる必要があります。そうでない場合、データはほとんど静的であるため、簡単にキャッシュできるため、線形にスケーリングできます。

ログイン、必要なデータの説明、最後にログオフを実装するプッシュメソッドは最も効率的ですが、平均的な「スクリプトキディ」にはおそらくあまりにも複雑であり、次の質問に対処する必要があります。ブラウザをシャットダウンしてログオフを実行できませんか?

たぶん、別のキャッシュサーバーにいくらかのお金を節約するよりも、より多くのユーザーがいる方が良いでしょう(アクセスは簡単です)?


1

何らかの理由で、最近では、すべての若いWeb開発者が過去の教訓を忘れてしまったようです。

  1. 帯域幅が問題でした
  2. 接続が断続的になる可能性があります。
  3. ブラウザにはそれほど多くの計算能力がありませんでした
  4. コンテンツにアクセスする他の方法がありました。Webはw3ではありません。

これらの制約に直面して、一定の双方向通信ができない場合があります。そして、OSIモデルを見ると、ほとんどの考慮事項は永続性を基礎となる接続から切り離すことを意味していることがわかります。

それを念頭に置いて、情報をプルするポーリング方法は、クライアント側の帯域幅と計算を削減するための優れた方法です。プッシュの台頭は、ほとんどの場合、クライアントが絶え間ないポーリングまたはWebソケットを実行することだけです。個人的に私が他のみんななら、私はトラフィック分析の手段としてポーリングの規則性を高く評価します。時間外のGET / POST要求はある種の中間の状況の男性に信号を送ります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.