私は現在、画像のリストを表示する Ruby on Rails プロジェクトに取り組んでいます。
このプロジェクトに不可欠なのは、Webページを更新する必要なく、新しい投稿をリアルタイムで表示することです。しばらく探してみたところ、PubNubなどのJavaScriptソリューションやサービスに出くわしました。ただし、提供されたソリューションのどれもまったく意味がありませんでした。
JavaScriptソリューション( ポーリング )では、次のことが起こります。
これは実際の例に翻訳すると奇妙に見えます:
私の意見では、解決策は次のようになります:
PubNubソリューションは基本的に同じですが、今回は、データを共有するために当事者間を歩くインターンがいます。
言うまでもなく、どちらのソリューションも、ロードするデータがない場合でもトリガーされるため、非常にエネルギーを消費します。
私の知識に関する限り、この実装方法がほとんどすべてのリアルタイムアプリケーションで使用される理由(論理的)はありません。
プッシュは、1人または限られた数のユーザーに適しています。
シナリオを変更して、1人の写真家と1000人のユーザー全員が写真のコピーを希望するようにします。写真家は1000パイルまで歩く必要があります。それらのいくつかは、施錠されたオフィスにいるか、床全体に広がっている可能性があります。または休暇中のユーザーで、現時点では新しい写真に興味がない。
写真家はいつも新しい写真を撮るのではなく、散歩に忙しいでしょう。
基本的に、プル/ポールモデルは、緩やかなリアルタイム要件を持つ多くの信頼性の低いリーダーに適しています(画像が10秒後にパイルに到着する場合、何が重要なのか)。
そうは言っても、プッシュモデルは多くの状況でさらに優れています。低レイテンシが必要な場合(撮影後に新しい写真5秒が必要な場合)、または更新がまれであり、頻繁かつ予測可能な要求が行われる場合(写真家が1日に新しい写真を生成するときに、写真家に10秒おきに尋ねる)、引き寄せは不適切です。それはあなたが何をしようとしているのかに依存します。 NASDAQ:プッシュ。気象サービス:プル。結婚式の写真家:おそらく引っ張る。ニュース写真代理店:おそらくプッシュ。
WebSockets について言及した人が1人だけであることには本当に驚きます。サポートは 基本的にすべての主要なブラウザーに実装されています です。
実際、PubNubはそれらを使用します。あなたのアプリケーションでは、ブラウザはおそらく、新しい写真が利用可能になるたびにブロードキャストするソケットにサブスクライブするでしょう。ソケットは写真を送信しませんが、ブラウザは非同期でダウンロードできるようにリンクのみを送信します。
あなたの例では次のようなものを想像してください:
これは、元のサンプルソリューションに多少似ています。クライアントはサーバーにデータを送信する必要がないため、ポーリングよりも効率的です(多分 heartbeats を除いて)。
また、他の人が述べたように、古いブラウザで機能する単純なポーリングよりも優れた他の方法があります( longpollingなど 。)
時々十分で十分です。
「リアルタイム」通信プロセスを実装するために考えられるすべての方法のうち、ポーリングがおそらく最も簡単な方法です。ポーリング間隔が比較的長い(つまり、瞬時ではなく秒、分、または時間)場合、ポーリングを効果的に使用できます。接続またはリソースのチェックによって消費されるクロックサイクルはそれほど重要ではありません。
HTTPプロトコルは、クライアントが要求を開始するためのものでなければならないという点で制限されています。サーバーは、クライアントの要求に応答しない限り、クライアントと通信できません。
したがって、実際の例を調整するには、次の制限を追加します。
この新しい制限により、投票以外にどのように実行しますか?
なぜ投票は受け入れられるのですか?実際には、すべてのソリューションが実際には低レベルのポーリングであるためです。
新しい画像が利用可能になり次第サーバーがあなたを更新する必要がある場合、通常はIPアドレスが頻繁に変更され、誰かがもう興味がないかどうかわからないため、クライアントは何らかの形式で送信する必要があります。キープアライブ信号、たとえば「私はまだここにいる、オフラインではない」
インターネット経由で送信できるのは単一のデータパケットだけなので、すべてのステートフル接続(TCP/IPなど)は同じように機能します。相手がまだそこにいるかどうかはわかりません。
したがって、すべてのプロトコルにはタイムアウトがあります。エンティティがX秒以内に応答しない場合、そのエンティティは死んでいると推定されます。したがって、データを送信せずにサーバーとクライアントの間の接続が開いているだけの場合でも、サーバーとクライアントは定期的なキープアライブパケットを送信する必要があります(これらの接続を開いた場合、これは低レベルで処理されます)。これは結局のところ、ポーリングとは異なりますか?
したがって、最善のアプローチはおそらくロングポーリングです:
クライアントはサイトをロードした直後にリクエストを送信します(たとえば、写真家に「新しい画像があるかどうかを教えて」と伝えます)が、サーバーは新しい画像がない場合は応答しません。リクエストがタイムアウトするとすぐに、クライアントは再度尋ねます。
サーバーが新しい画像を持っている場合、新しい画像を待っているすべてのクライアントにすぐに応答できます。したがって、クライアントはまだオープン接続で応答を待機しており、クライアントへの接続を確立する必要がないため、新しい画像が表示された後の反応時間はプッシュよりもさらに短くなります。また、クライアントからのポーリングリクエストは、クライアントとサーバー間の常時接続よりもはるかに多くのトラフィックではありません。
ポーリングの利点の1つは、メッセージが失われたり、何かの状態に問題が発生した場合に発生する可能性のある害を制限することです。 XがYに5秒ごとに状態を要求する場合、要求または応答が失われると、Xの情報が5秒ではなく10秒古くなるだけです。Yが再起動すると、Xは次の情報を知ることができます。時間YはXのメッセージの1つに応答できます。 Xが再起動した場合、後でYに何かを要求することはありませんが、Xのステータスを監視している人は誰でも、Xが再起動されたことを認識しているはずです。
XがYをポーリングする代わりに、XがYに依存してその状態が変化するたびに通知する場合、Yの状態が変化してXにメッセージを送信した場合、何らかの理由でそのメッセージが受信されなかった場合、Xは変更に気付かない可能性があります。 。同様に、Yがリブートされ、Xに何かに関するメッセージを送信する理由がない場合。
場合によっては、Xが定期的にまたは変更されたときにYにステータス付きのメッセージを自律的に送信するように要求し、Yから何も聞かずに長くなりすぎた場合にのみXポーリングを行うと役立つ場合があります。このような設計により、 Xがほとんどのメッセージを送信する必要がある(通常、Xは少なくともたまにYにまだメッセージの受信に関心があることを通知し、Yが関心を示さずに長すぎる場合はメッセージの送信を停止する必要があります)。ただし、そのような設計では、Yに永続的に Xに関する情報を維持するように要求します。ポーリングした人に応答を送信し、それが誰なのかをすぐに忘れるのではありません。 Yが組み込みシステムの場合、そのような簡略化により、メモリ要件を十分に削減して、より小型で安価なコントローラーを使用できるようになります。
ポーリングは、信頼性が低い可能性のある通信メディア(UDPや無線など)を使用する場合に追加の利点があります。リンク層の確認応答の必要性を大幅に排除できます。 XがYにステータス要求Qを送信し、YがステータスレポートRで応答し、XがRを聞いた場合、Xが受信したことを知るために、Xがリンク層の確認応答を聞く必要はありません。逆に、YがRを送信すると、XがRを受信したかどうかを知る必要も、気にする必要もありません。 Xがステータス要求を送信し、応答がない場合、Xは別の要求を送信できます。 Yがレポートを送信し、Xがそれを聞いていない場合、Xは別の要求を送信します。各リクエストが1回送信され、応答が返されるか、返されない場合、どちらの当事者も、特定のメッセージが受信されたかどうかを気にする必要はありません。確認応答を送信すると、ステータス要求またはレポートとほぼ同じ帯域幅が消費される可能性があるため、要求レポートの往復を使用しても、非送信請求レポートおよび確認応答よりもコストはかかりません。 Xが応答なしでいくつかの要求を送信する場合、一部の動的にルーティングされるネットワークでは、リンクレベルの確認応答を有効にする必要があり(その要求でYも同様に要求する)、基礎となるプロトコルスタックが配信の問題を認識して検索できるようにする必要があります。新しいルートですが、物事が機能している場合、要求レベルのレポートモデルは、リンクレベルの確認応答を使用するよりも効率的です。
何らかの理由で、最近、すべての若いWeb開発者は過去の教訓を忘れてしまったようです。
これらの制約に直面すると、常に双方向の通信ができない場合があります。また、OSIモデルを見ると、ほとんどの考慮事項は、永続性と基礎となる接続を分離することを目的としていることがわかります。
これを念頭に置いて、情報をプルするポーリング方法は、クライアント側の帯域幅と計算を削減するための優れた方法です。 Pushの台頭は、実際には、ほとんどの場合、一定のポーリングを行うクライアント、つまりWebソケットだけです。個人的に私がそこにいる全員なら、トラフィック分析の手段としてポーリングの規則性を高く評価します。ここで、GET/POSTリクエストのタイムアウトは、ある種の中間の状況にある人に信号を送ります。
問題は、不必要な世論調査の量と不必要なプッシュの量のバランスをとることです。
投票した場合:
プッシュする場合:
さまざまなシナリオとその欠点に対処する方法にはいくつかの解決策があります。たとえば、ポーリング間の最小時間、メインシステムから負荷を取り除くためのポーリング専用プロキシ、または-プッシュの場合-登録および指定する規制必要なデータと、その後のログオフ時の登録解除。どちらが最適かは、一般的に言えないことであり、システムによって異なります。
あなたの例では、ポーリングは最も効率的なソリューションではありませんが、最も実用的なソリューションです。 JavaScriptでポーリングシステムを作成するのは非常に簡単で、配信側にも実装するのは非常に簡単です。画像データを配信するために作成されたサーバーは、追加の要求を処理できる必要があります。そうでない場合、データはほとんど静的であり、したがって簡単にキャッシュできるため、線形にスケーリングできます。
ログイン、必要なデータの説明、最後にログオフを実装するPushメソッドは最も効率的ですが、平均的な「スクリプトキディ」にはおそらく複雑すぎて、質問に対処する必要があります。ブラウザをシャットダウンしただけでログオフできませんか?
たぶん、別のキャッシュサーバーにいくらかお金を節約するよりも(アクセスが簡単なので)より多くのユーザーを持つ方が良いでしょうか?