web-dev-qa-db-ja.com

キュー(SQSなど)ジョブが完了したことをクライアントにリアルタイムで通知する最良の方法は?

現在のシナリオ

私たちのアプリケーションでは、ユーザーが私たちのインターフェースを介してファイルをアップロード(Amazon S3)し、ファイルを管理できます。現在、これらのユーザーは、アプリケーションを介してS3/Cloudfrontから直接ファイルをダウンロードできます。

Zip機能の追加

システムに機能を追加して、ユーザーが一度に複数のファイルを選択してZipファイルとしてダウンロードできるようにします。

ユーザーがボタンをクリックしてZipファイルをダウンロードすると、システムがリクエストを処理してZipをコンパイルし、Zipをエンドユーザーに返すように、プロセスがリアルタイムで機能するようにします。プロセスの実行中、フロントエンドは要求が処理中であることをユーザーに通知し、プロセスが完了すると、ファイルのダウンロードを要求します。

提案された戦略

私たちのアプリケーションはAWSクラウドベースであるため、最初の本能は Amazon SQS (ただし他の提案を受け入れる)を使用してこれらのリクエストを処理するキューシステムを構築することです。フローは次のように機能します。

  1. ユーザーはファイルを選択し、Zipファイルの作成を要求します。
  2. フロントエンドは、ZIPされるファイルと最終的なZipファイルが保存される宛先(S3上の)を含むリクエストをSQSに送信します。
  3. キューワーカーは ロングポーリング を使用して、新しいSQSジョブをチェックします。ジョブが見つかると、ワーカーはS3からファイルをダウンロードして圧縮し、完成したZipファイルをS3の指定された場所に返します。
  4. キューの処理が完了したので、ジョブが完了し、ファイルをダウンロードする準備ができていることをクライアントに警告します。

ステップ4を処理する最良の方法?

このプロセスは堅実なアプローチのようで、ステップ4まですべてが理にかなっています。エンドユーザーにジョブが完了し、ファイルをダウンロードする準備ができていることをリアルタイムで通知する最善の方法に取り組んでいます。

私の研究から、私は人々が提案する3つの方法を見てきました。

  1. Pub/subを使用してジョブのソケットを作成し、完了したら応答を返します。

    • 私が読んだすべてのことから、多数のオープンpub/subソケット/チャネルを作成することはベストプラクティスではありません(場合によっては不可能です)。さらに、SQSはジョブが完了したことをオープンソケットにどのように通知しますか? Amazon SNSに関するこの記事 は最初は有望に見えましたが、ジョブごとのSNSトピックではなく、キュー全体に対して単一のSNSトピックを使用することがベストプラクティスであると推察しています。これは、単にユーザーにメールを送信して、仕事が終了したことを知らせるだけの場合は、素晴らしいアプローチのようです。ただし、Webブラウザー内のユーザーインターフェイスを更新できるようにしたいと考えています。
  2. S3上の完成したZipファイルに対するフロントエンドサーバーによる継続的なポーリング。

    • 数千の同時ジョブがある場合、これにより数千のリクエストが作成されます。このアプローチはあまりスケーラブルではないようであり、追加のS3 api呼び出しによって潜在的に費用がかかる可能性があります。
  3. オープンな実行中のリクエストを残す

    • キューに多くのジョブがある場合、応答の配信に時間がかかるため、要求がタイムアウトになる可能性があるためです。さらに、これはフロントエンドWebサーバーに多くの負担/無駄なリソースを作成します。繰り返しますが、あまり拡張性がありません。

私の質問

上記のポイントを考慮して、ジョブキューが完了し、ファイルをダウンロードする準備ができたことをフロントエンドクライアントに通知する最良の方法は何ですか?

私がやろうとしていることの良い例がYouTubeです。動画をYouTubeにアップロードすると、キューが動画を処理し、完了すると、動画処理が完了したことを通知します。私のシナリオでは、ZipファイルがいつS3にアップロードされたのかをクライアントに知らせたいという点を除いて、同じコンセプトを複製しようとしています。

私は理論的な解決策を知っているので、具体的に教えてください。 SQSを使用しているか、リストに挙げたテクノロジー/方法論を使用しているかに関係なく、私はどんな提案にも応じます。この種のものの実際のコード例を示すことは大きなボーナスになります。

よろしくお願いします!

7
Slickrick12

私の考えは、フロントエンドがサーバー送信イベント( https://developer.mozilla.org/en-US/docs/Server-sent_events/Using_server-sent_events )を発行するWebサーバーを確立することですSQSを介してワーカーにジョブを実行するメッセージ。ワーカーが完了すると、別のキューのWebサーバーにメッセージを追加します。このキューは、一度にメッセージのバッチについてポーリングされ、それぞれがイベントをクライアントに送り返します。

クライアントとサーバーがやり取りしないため、Webソケットを使用する必要はありません。

0
Kevin