7

本当の質問に入る前に、いくつかの背景:

私はいくつかの異なるモジュールで構成されるバックエンドアプリケーションに取り組んでいます。現在、各モジュールはコマンドラインJavaアプリケーションであり、「オンデマンド」で実行されます(詳細は後で説明します)。

各モジュールは「ステップ」であり、データフローと考えることができるより大きなプロセスの一部です。最初のステップでは、外部ソースからデータファイルを収集し、それらをいくつかのSQLデータベーステーブルにプッシュ/ロードします。次に、さまざまな条件とイベント(タイミング、DB内のデータの存在、Webサービス/ Webインターフェイスを介して行われるメッセージと詳細)に基づいて、(1つ以上の)DBテーブルからデータを取得し、それらを処理します。それらを別のテーブルに書き留めます。ステップは3つの異なるサーバーで実行され、3つの異なるDBからデータを読み取りますが、単一のDBにのみ書き込みます。目的は、データを集約し、メトリックと統計を計算することです。

現在、各モジュールは定期的に実行されます(最初のモジュールの数分/時間から、チェーンの最後の数日まで、より多くのデータを集約する必要があるため、それらが利用可能になるまで「より長く」待機する必要があります)。 cronjob。モジュール(現在はJavaコンソールアプリケーション)が実行され、指定された日時ウィンドウ内の新しい未処理の情報がないかデータベースをチェックし、そのジョブを実行します。

問題:それは機能しますが、..私はそれを拡張して維持する必要があり、このアプローチはその限界を示し始めています。

  1. 私は「ポーリング」に頼るのは好きではありません。以前のモジュールの情報は、必要な情報が利用可能になったときにチェーンの下流にある他のモジュールに「伝える」のに十分であり、続行できることを考えると、無駄です。
  2. それは「遅い」です。データが到着し、前のモジュールによって処理されていることを確認する必要があるため、チェーンの下位のモジュールには数日間の遅延があります。したがって、すべてのデータが確実に得られるまで、これらのモジュールを「停止」します。新しい追加には、いくつかのメトリックのリアルタイム(難しいことではありませんが、「できるだけ早く」)の計算が必要です。非常に良い例は、ここで、バッジを使用してSOで何が起こるかです。:)私は本当に似たものを入手する必要があります。

2番目の問題を解決するために、「部分的」または「漸増的」計算を導入します。関連する情報のセットがある限り、それを処理します。次に、他のリンクされた情報が到着したら、差を計算してそれに応じてデータを更新しますが、他の(依存する)モジュールにも通知する必要があります。

質問)

-1)それを行うための最良の方法はどれですか?--2)関連:関連データが利用可能であることを他のモジュール(私の場合はJava実行可能ファイル)に「通知」するための最良の方法はどれですか?

私は3つの方法を見ることができます:

  • 他の「非データ」テーブルをDBに追加します。このテーブルには、各モジュールが「ねえ、私はこれを実行し、使用可能です」と書き込みます。cronjobが別のモジュールを開始すると、テーブルを読み取り、サブセットxxxを計算できると判断して実行します。等々
  • DBテーブルの代わりに、ZeroMQなどのメッセージキュー(または@mjnが提案するようなApache Camel)を使用します
  • DBテーブルの代わりに、RedisなどのKey-Valueストアを使用する

編集:キューに基づくアプローチが進むべき道であると確信しています。完全を期すために「テーブル+ポーリング」オプションを追加しましたが、これは気を散らすものにすぎないことを理解しています(明らかに、誰もが「はい、キューを使用します」と答えます。 、ポーリングは悪です」-そして当然のことながらそうです!)。では、質問を次のように言い換えます。Redisの ようなpub / subを備えたKey-ValueストアよりもMQを使用することの長所/短所は何ですか?

  • 3)cronjobを完全に取り除くのに役立つ解決策はありますか?

編集:特に、場合によっては、それは次のことを意味します:「時間」でメッセージを公開できるようにするメカニズムが一部のMQおよび/またはKey-Valueストアにありますか?「1日で届ける」みたい?永続性と「ほぼ1回」の配信保証により、明らかに

  • 4)このメッセージ(イベント?)ベースのソリューションを集中型サービスとして構築し、サーバーの1つでデーモン/サービスとして実行する必要がありますか?
  • 5)サブスクライバーをオンデマンドで開始するというこのアイデアを放棄し、各モジュールをデーモン/サービスとして継続的に実行する必要がありますか?
  • 6)長所と短所はどれですか(信頼性、単一障害点とリソースの使用量および複雑さ...)?

編集:これは私が最も気にかけているビットです:MSMQアクティベーションと同様に、キュー内のメッセージに基づいて「モジュール」をアクティブ化するためにそれ自体を「キューに入れ」たいと思います。それは良い考えですか?Javaの世界でそれを行うものはありますか?それを自分で実装する必要がありますか(MQまたはRedisを介して)、または各モジュールをデーモンとして実行する必要がありますか?(一部の計算が通常バーストで発生する場合でも、2時間の処理とそれに続く2日間のアイドリング?)

注:重いコンテナ/ EJBを使用できません(Glassfishな​​どは使用できません)

編集:ラクダも私には少し重すぎるようです。リソースと開発の複雑さの両方の観点から、ここで本当に軽いものを探しています

4

3 に答える 3

1

1>メッセージキューを使用することをお勧めします。要件に応じてキューを選択しますが、ほとんどの場合、プロトコルJMS(アクティブmq)またはAMQP(ウサギmq)に基づいてキューを選択し、単純なものを作成することをお勧めします。その上にラッパーを作成するか、spring->spring-jmsまたはspring-amqpによって提供されるものを使用します

2>新しいメッセージが到着したことをシステムに通知するようにキューコンシューマーを作成できます。たとえば、ウサギでは、MessageListenerインターフェースを実装できます。

 public class MyListener implements MessageListener {
     @Override
public void onMessage(Message message) {
     /* Handle the message */        

    }
}

3> <2>のように非同期コンシューマーを使用すると、すべてのポーリングおよびcronジョブを取り除くことができます

4>要件によって異なります->キューを通過するイベント/メッセージが数百万ある場合は、集中型サーバーでキューミドルウェアを実行するのが理にかなっています。

5>リソースの消費が問題にならない場合は、コンシューマー/サブスクライバーを常に実行し続けるのが最も簡単な方法です。これらの消費者が分散している場合は、飼育係などのサービスを使用してそれらを調整できます

6>スケーラビリティ->ほとんどのキューイングシステムはメッセージの簡単な配布を提供するため、コンシューマーがステートレスであれば、新しいコンシューマーといくつかの構成を追加するだけでスケーリングが可能です。

于 2013-03-15T05:59:51.677 に答える
1

キュータスクの説明は、 ApacheCamelのような「エンタープライズ統合パターン」に基づくシステムのように部分的に聞こえます。

遅延メッセージは定数で表すことができます

from("seda:b").delay(1000).to("mock:result");

または変数、たとえばメッセージヘッダー値

from("seda:a").delay().header("MyDelay").to("mock:result");
于 2013-03-07T11:41:55.870 に答える
0

それを実装した後、私自身の質問に答えることは、将来StackOverflowにアクセスする人々にとって良いことだと思います。

結局、私はRedisと一緒に行きました。それは本当に高速でスケーラブルです。そして、私はその柔軟性がとても好きです。メッセージキューよりもはるかに柔軟性があります。RedisはさまざまなMQよりもMQの方が優れていると私は主張していますか?まあ、私の特定のケースでは、私はそう信じています。重要なのは、何かがすぐに提供されない場合は、それを構築できることです(通常、MULTIを使用しますが、LUAを使用してさらに高度なカスタマイズを行うこともできます!)。

たとえば、私はこの良い答えに従って、「永続的」で回復可能なpub / sub(つまり、クライアントがメッセージを失うことなく停止して再接続できるようにするpub / sub)を実装しました。

これは、スケーラビリティと「信頼性」の要件の両方に役立ちました。パイプライン内のすべての部分を独立させておくことにしました(今のところデーモン)が、Redisのリスト/キューを調べるモニターを追加します。何かが消費されていない(または消費が遅すぎる)場合、モニターは新しいコンシューマーを生成します。また、真に「弾力性のある」ものであり、仕事がないときに消費者が自殺できるようにすることも考えています。

別の例:スケジュールされたアクティビティの実行。今のところ、非常に人気があるように思われるこのアプローチに従っています。しかし、私はキースペース通知を試して、期限切れのキーと通知の組み合わせが優れたアプローチになるかどうかを確認したいと思っています。

最後に、Redisにアクセスするためのライブラリとして、私の選択はJedisに行きました。これは人気があり、サポートされており、リスナーとしてpub/subを実装するための優れたインターフェイスを提供します。これはScalaでの(慣用的な)最善のアプローチではありませんが、うまく機能します。

于 2013-07-25T13:37:44.680 に答える