3

ここに理論的な質問があります:

メッセージ キューイングを使用してアプリケーションを構築する場合、さまざまな目的でさまざまなデータ型をサポートする複数のキューが必要になります。20 個のキューがあるとします (たとえば、新しいユーザーを作成するためのキュー、新しい注文を処理するためのキュー、ユーザー設定を編集するためのキューなど)。

1 つの Web ロールと 1 つのワーカー ロールの「最小」を使用して、これを Windows Azure に展開します。

これら 20 個のキューすべてから適切な方法で読み取るにはどうすればよいでしょうか? これは私が念頭に置いていたことですが、これに関する実際の実際の経験はほとんどまたはまったくありません。

worker ロールの「メイン」クラスで 20 個のスレッドを生成するクラスを作成します。これらの各スレッドに、異なるキューをポーリングするメソッドを実行させ、各ポーリング間でこれらすべてのスレッドをスリープ状態にします (もちろん、スリープ時間を増やすバックオフ メカニズムを使用します)。

これにより、20 個のスレッド (または 21 個?) と 20 個のキューがアクティブにポーリングされることになり、多くの無駄なメッセージが発生します (空のキューをポーリングするたびに、メッセージとして課金されます)。

この問題をどのように解決しますか?

4

3 に答える 3

5

私は他の答え(非常に良い答え)を読んで、これに自分のスピンを入れたいと思いました。

@Lucifureが説明したように、Windows Azureキューに固執する:2つのシナリオを除いて、複数のキューの必要性は実際にはわかりません。

  • 異なる優先順位が必要です。最後に必要なのは、優先度の高いメッセージが何百もの優先度の低いメッセージの背後に詰まっていることです。これらのhi-priキューを作成します。
  • メッセージの読み取りと削除の数は、1秒あたり500トランザクションの目標を超えます。この場合、複数のキューを作成して、トランザクションボリュームをストレージパーティション全体に分散させます(ストレージアカウントは1秒あたり5K以上のトランザクションを処理します)。

単一のキュー(サービスバスではなくストレージベース)を使用する場合は、メッセージのブロックを一度に読み取ることができます(最大32)。メッセージタイプを区別するのに役立つフォーマットを簡単に作成できます(おそらく単純なプレフィックスを使用)。次に、メッセージを適切なスレッドに渡して処理します。Service Busキューにはマルチメッセージ読み取りはありませんが、プリフェッチは可能です(これにより、バッファリングされたメッセージがキャッシュにダウンロードされます)。

多くのキューに対する1つのキューの利点:「多くのキューにメッセージがなく、読み取りが空になる」という問題を取り除く(または大幅に減らす)。

より多くのスループットが必要な場合は、キューの読み取りとディスパッチを実行するスレッドの数をいつでも増やすことができます。

各削除はアトミックであることを忘れないでください。バッチ処理はありません。そして、キューポーリングに関する限り、バックオフについて考えるのは正しいことです。メッセージ(またはメッセージのチャンク)を正常に読み取った後、バックオフする必要はありません。読み込もうとして何も得られない場合は、元に戻してください。

Service Busキューに対する優れた利点の1つは、Windows Azureキューがおおよそのメッセージ数を提供することです(これは、複数のインスタンスへのスケールアウトを検討するときに非常に役立ちます)。ServiceBusキューはこれを提供しません。

于 2012-06-10T04:36:14.227 に答える
2

別の戦略は、キューが複数のタイプのメッセージをサポートできるように、単一以下のキューを使用することです。このアプローチは、システムアーキテクチャでサポートできる場合、管理が容易で安価です。

現実の世界では、(スケーラビリティの目的で)複数のキューを正常に使用しました。各キューは、タイマーイベントによってトリガーされる個別のスレッドで読み取られます。キューの負荷とアプリケーションのニーズに応じて、動的に変化する間隔でキューを処理するようにタイマーイベントが変更されました。

于 2012-06-09T22:48:07.430 に答える
1

ストレージ キューのバックオフ メカニズムが十分でない場合は、Service Bus キューを検討することをお勧めします。Service Bus キューを使用すると、そのような積極的なポーリングを行う必要がなくなります。

キューをポーリングするためのループを実装する必要がありますが、受信タイムアウトにより、ストレージ キューを使用する場合の定期的なポーリング メカニズムよりも軽くなります。

次の例では、キューからメッセージを受信しようとしています。メッセージが見つからない場合は、接続を 30 秒間開いたままにして、新しいものが入ってくるかどうかを確認します。30 秒経ってもメッセージが届かない場合、Receive メソッドは null を返します (そして、Receive を再度呼び出そうとするループが発生します)。最大タイムアウトは 24です。

MessagingFactory factory = MessagingFactory.Create(ServiceBusEnvironment.CreateServiceUri("sb", ServiceNamespace, string.Empty), credentials); 
QueueClient myQueueClient = factory.CreateQueueClient("TestQueue");
myQueueClient.Receive(new TimeSpan(hours: 0, minutes: 0, seconds: 30));

読み取り元のキューごとにスレッドをポップアップすることは良い考えですが、CLR スレッド プールの容量制限を考慮して、非同期でメッセージを受信することも検討する必要があります (たとえば、 TaskFactory.FromAsyncを使用): http://msdn.microsoft. com/en-us/library/windowsazure/hh851744.aspx

于 2012-06-09T22:31:00.023 に答える