2

私は定期的に多数の IO バインド操作を実行する必要がある Rails アプリケーションに取り組んでいます。これらの操作は非同期で実行できます。たとえば、システムは 1 日に 1 回、ユーザーごとに Salesforce.com にクエリを実行して、追跡しているユーザーの現在のアカウント (会社) のリストを取得する必要があります。これにより、膨大な数 (潜在的に > 100k) の小さなクエリが発生します。

私たちの現在のアプローチは、ActiveMessaging で ActiveMQ を使用することです。各ユーザーは、異なるメッセージとしてキューにプッシュされます。次に、コンシューマーはユーザーをキューから引き出し、Salesforce.com にクエリを実行し、結果を処理します。しかし、このアプローチはひどいパフォーマンスをもたらします。1 つのポーラー プロセス内では、一度に 1 人のユーザーしか処理できません。したがって、Salesforce.com クエリはシリアル化されます。文字通り何百ものポーラー プロセスを実行しない限り、ポーラーを実行しているサーバーを飽和状態に近づけることはできません。

代替手段として EventMachine を検討しています。これには、単一の EventMachine プロセス内で多数の Salesforce.com クエリを同時に開始できるという利点があります。そのため、サーバーの優れた並列処理と使用率が得られます。

しかし、EventMachine には 2 つの問題があります。1) ActiveMQ/ActiveMessaging で得られた信頼性の高いメッセージ配信が失われます。2) EventMachine を定期的に再始動して、メモリー増加の影響を軽減することは容易ではありません。たとえば、ActiveMessaging では、1 日に 1 回ポーラーを再起動する cron ジョブがあり、これはメッセージを失うことを心配することなく実行できます。しかし、EventMachine では、プロセスを再開すると、進行中の何百ものメッセージが文字どおり失われる可能性があります。これを回避できる唯一の方法は、EventMachine の上に持続性と信頼性の高い配信レイヤーを構築することです。

誰もがより良いアプローチを持っていますか? 大量の非同期 IO バウンド操作を確実に実行するための最良の方法は何ですか?

4

4 に答える 4

2

私は ActiveMessaging を維持しており、マルチスレッド ポーラーの問題についても考えていますが、おそらく皆さんと同じ規模ではありません。ここで私の考えを述べますが、アクティブなメッセージ リストや、必要に応じて電子メールでさらに議論したいと思います。

トリックの 1 つは、ポーラーだけがシリアル化された部分ではないということです。STOMP サブスクリプションでは、割り込み時にメッセージが失われるのを防ぐために client -> ack を実行すると、前のメッセージが確認応答された場合にのみ、特定の接続で新しいメッセージが送信されます。基本的に、接続ごとに一度に処理できるメッセージは 1 つだけです。

したがって、ブローカーを使い続けるには、多くのブローカー接続/サブスクリプションを一度に開いておくのがコツです。現在のポーラーは、ポーラーごとにレール環境全体をロードし、1 つのポーラーが 1 つの接続であるため、これにはかなり重いです。しかし、現在のポーラーには魔法のようなものは何もありません。ブローカへの新しい接続を作成し、一度に多くのメッセージを取得するために実装されるイベント マシン クライアントとしてポーラーを作成することは想像できます。

最近の私自身の実験では、Ruby Enterprise Edition を使用し、多くのポーラー ワーカー スレッドをフォークするマスター スレッドを用意して、メモリ フットプリントを削減することを考えていました (パッセンジャーのように)。同様に機能する可能性があります。

私は Resque プロジェクトのファンでもありますが、それが多くのワーカーへのスケーリングに優れているかどうかはわかりません。

http://github.com/defunkt/resque

于 2010-01-25T17:54:38.200 に答える
2

私は、あなたのために働く方法で、RabbitMQ で AMQP を使用しました。ActiveMQ は AMQP を実装しているので、同様の使い方ができると思います。私は ActiveMessaging を使用したことがありません。素晴らしいパッケージのように見えますが、このユース ケースには適していないのではないかと思います。

AMQP を使用してそれを行う方法は次のとおりです。

  • Rails プロセスに「ユーザー i の情報を取得してください」というメッセージを送信させます。
  • コンシューマはこれをメッセージ キューから取り出し、キューから永久に削除するにはメッセージが「ack」を必要とすることを確実に指定します。これは、メッセージが処理されたことが確認されない場合、最終的に別のワーカーのキューに戻されることを意味します。
  • その後、ワーカーはメッセージをセールスフォースへの数千の小さなリクエストに分割します。
  • これらのリクエストがすべて正常に返されたら、別のコールバックを起動して元のメッセージを確認し、元のリクエストに関連するすべての情報を含む「要約メッセージ」を返す必要があります。重要なのは、特定のメッセージの処理が成功したことを確認できるメッセージ キューを使用し、関連する処理が完了した場合にのみそうするようにすることです。
  • 別のワーカーがそのメッセージをキューから取り出し、適切な同期作業を実行します。レイテンシを誘発するすべてのビットがすでに実行されているので、これで問題ないと思います。

(C)Ruby を使用している場合は、単一のプロセスで同期と非同期のものを組み合わせないようにしてください。プロセスは、コードをブロックせずに Eventmachine を介してすべてを行うか、メッセージ キューを介して Eventmachine プロセスとのみ通信する必要があります。

また、非同期コードを書くことは非常に便利ですが、書くのもテストするのも難しく、バグが発生しやすくなります。気をつけて。必要に応じて、別の言語またはツールを使用して調査します。

于 2010-01-25T19:32:49.473 に答える
1

「けいれん」と「豆の木」もチェックアウト

于 2010-01-26T18:38:00.253 に答える
0

誰かが私に次のリンクを送ってくれました:http://github.com/mperham/evented/tree/master/qanat/。これは、EventMachineの上に構築されていることを除けば、ActiveMessagingにいくぶん似ているシステムです。それはほぼ正確に私たちが必要としているものです。唯一の問題は、ActiveMQではなくAmazonのキューでのみ機能するように見えることです。

于 2010-01-27T18:40:43.423 に答える