web-dev-qa-db-ja.com

高性能ファイル処理Webアプリケーションの設計

スケーリングできる機能を備えたWebアプリを設計しようとしていますが、いくつかの概念に頭を抱えることはできません。私はそれを正しく設計したいのですが、経験豊富なプログラマーではありません。システムエンジニアリングの知識が豊富です。

基本的なアーキテクチャは次のようになります。

Webサーバー->ファイル処理サーバー-> NoSQL DB->検索サーバー

したがって、主なシナリオは次のとおりです。

  • ユーザーがサイト経由でファイルをアップロードする
  • ファイルはサーバーに処理のために送信されます(Pythonスクリプト)
  • 処理結果はNoSQL DBに送信されます
  • 検索サーバーによって処理され、ユーザーに返された結果

ロードバランシングを介してWebフロントエンドをスケーリングできます。 nginx + Apacheのようなもの。
データベースのスケーリングはCassandraまたはMongoDBによって処理されます。検索スケーリングはelasticsearchまたはsphinxクラスタリングによって処理されます。

アップロードしたファイルが大きすぎる場合に備えて、複数のファイル処理サーバーを追加できるようにしたいと思います。だから私はどういうわけかファイルをチャンクに分割し、複数のノードで同時に処理する必要があります。さらに、作業中にノードがダウンしても、何も影響を受けず、データを保存する必要があります。したがって、ファイル処理サーバーにタスクを割り当て、負荷のバランスをとり、タスクの実行を制御する別のものが必要です。

そのようなことのためのカスタムアプリケーションをどのように設計するのですか?メッセージキューイングを使用する必要がありますか?

6
Coolface

メッセージキューイングは、ユーザーが処理が完了するのを待つ必要があるという考えを破棄するとともに、あなたの答えだと思います。ユーザーがファイルをアップロードしたら、それをメッセージ「プロセッサー」にキューイングし、予備的な分析を行います(基本的に、ファイルが大きすぎるかどうかを判断し、「スプリッター」キューに転送するか、単に通常の処理キューに入れます。 )。この時点で、処理が完了したときに結果にアクセスするためにユーザーが使用できるトークンまたはURLをユーザーに返す必要があります。このようにして、タイムアウトやセッションをアクティブに保つことを心配する必要はありません。ユーザーは、ファイルを再処理せずに結果をもう一度表示したい/必要がある場合に備えて参照を利用できます。

1
TMN

最近のコンピュータの電力は安いです。さらに、ボトルネックがどこにあるかはまだわかりません。

私には、これは負荷がかかる前にパフォーマンスを心配する時期尚早の最適化のようなにおいがします。多分あなたはそれを機能させることから始めて、それからそれをスケーリングすることについてだけすべきです。私の2セント。

問題は、迅速な処理時間または高いスループットが必要かどうかにもあります。処理が本当にリソース/時間を集中的に使用する場合、ファイルを分割し、それを配布して結果をマージすることは理にかなっています。ただし、これらはもちろん、分割、送信、出力のスケジュール、マージ、パーツの障害の処理など、特定のコストがかかります。これらのタスクもリソースを消費し、非常に複雑になります。分散計算は、適切なタスクにのみ適しています。サーバーごとに単一のタスクを計算する方が、これらすべてのものを実行するよりも効率的である場合があります。

1
dagnelies

ファイル全体がある場合にのみサーバーにアクセスするには、ajax(または非同期callbackまたはhandler)を使用する必要があるため、分割する必要はありません。ファイルをチャンクに分割します。ファイルが処理されることをユーザーに伝え、ファイルが終了したらメッセージを送信します。

そこから、アップロードしたファイルごとに(サーバーで)非同期ワーカーメソッドを使用して、pythonスクリプトに送信して処理することができます。

0
tatigo

私があなたがやっていることを完全に理解しているとは思えません(「ファイルが '処理のために送信された]とはどういう意味ですか処理?)。多分それは文脈にとってそれほど重要ではありません。

私の最初の本能は、「アップロードプロセスの一部として」「処理」がアプリサーバーで実行できない理由を尋ねることだと思います。次に、アプリサーバーに使用するスケーリングソリューションが何であれ、「処理」はそれに合わせてスケーリングします。

ただし、独立して調整可能なサブシステムを使用して、大規模にスケーラブルなソリューションを設計しようとしているため、アプリサーバーを「処理」イベントにリンクしたくないというヒントも得られます。その場合、いくつかの異なる方法があります。

私は以前に、このタイプの問題にメッセージキュー(提案したとおり)を使用しました。次に、負荷が増加したときに追加のリスナーを起動します。ただし、使用するトリガーメカニズムに注意する必要があり、トランザクション処理(同期点/ロールバックおよびコミット)を適切に処理する必要があります。そうしないと、キューイングがデバッグの混乱につながる可能性があります。ささいなことのようですが、私の経験ではそうではありません。すべてが機能しているときは素晴らしいことですが、曇りの日のシナリオを完全にテストして、メッセージのドロップやメッセージの処理が2回以上行われないようにする必要があります。 「保証付き配達」は、それがすべてであるとは限らない。

最近、共有メモリデータグリッド(Hazelcast)を使用して、このような問題も解決しました。 APIは実際にキューを実装するため、上記のソリューションの場合のようにキューマネージャーを設定するためのオーバーヘッドはありません。私の場合、テーブルから数千億のデータ行に対して変換プロセスを実行する必要があり、テーブルのさまざまなポイントでテーブルリーダーを起動するマルチスレッドアプリを作成することで、レコードをデータグリッドに投げました。そして、データを変換するために必要なだけインスタンス化できる別のプロセスを書いたので、必要に応じてスケーリングできました。私はそれが上記のソリューションの単なるバリエーションだと思います。元のアプローチで実行するのに約3日かかったプロセスを約15分で実行しましたが、その15分間で50ノードのクラスターに分散されました。

0
Calphool