1

Azure Service Bus のサブスクリプションに存在するすべての仲介メッセージを読み取るためのコンソール アプリケーションがあります。そこには約3500のメッセージがあります。これはメッセージを読むための私のコードです:

SubscriptionClient client = messagingFactory.CreateSubscriptionClient(topic, subscription);   
long count = namespaceManager.GetSubscription(topic, subscription).MessageCountDetails.ActiveMessageCount;
Console.WriteLine("Total messages to process : {0}", count.ToString()); //Here the number is showing correctly
IEnumerable<BrokeredMessage> dlIE = null;
dlIE = client.ReceiveBatch(Convert.ToInt32(count));

コードを実行すると、dlIE で 256 個のメッセージしか表示されません。私もこのようにプリフェッチ カウントを指定しようとしましclient.PrefetchCountたが、256 メッセージしか返されません。

一度に取得できるメッセージの数には制限があると思いますが、メソッドのmsdnページにはそのようなことは記載されていませんRecieveBatch。一度にすべてのメッセージを取得するにはどうすればよいですか?

ノート:

  1. 私はメッセージを読んで、サービスバスに存在させたいだけです。message.completeしたがって、メソッドは使用しません。

  2. Service Bus からトピック/サブスクリプションを削除して再作成できません。

編集:

次のように、ReceiveBatch の代わりに PeekBatch を使用しました。

    IEnumerable<BrokeredMessage> dlIE = null;
                            List<BrokeredMessage> bmList = new List<BrokeredMessage>();
  long i = 0;
   dlIE = subsciptionClient.PeekBatch(Convert.ToInt32(count)); // count is the total number of messages in the subscription.
  bmList.AddRange(dlIE);
  i = dlIE.Count();
 if(i < count)
  {           
 while(i < count)
  {
  IEnumerable<BrokeredMessage> dlTemp = null;
   dlTemp = subsciptionClient.PeekBatch(i, Convert.ToInt32(count));
    bmList.AddRange(dlTemp);
    i = i + dlTemp.Count();
    }
    }

サブスクリプションに 3255 件のメッセージがあります初めて peekBatch が呼び出されたとき、250 のメッセージを受け取ります。で while ループに入りPeekBatch(250,3225)ます。毎回 250 件のメッセージしか受信されません。出力リストにある最終的な合計メッセージは、重複を含む3500です。これがどのように起こっているのか理解できません。

4

3 に答える 3

3

私はそれを理解しました。サブスクリプション クライアントは、最後に取得したバッチを記憶しており、再度呼び出されたときに次のバッチを取得します。

したがって、コードは次のようになります。

    IEnumerable<BrokeredMessage> dlIE = null;
List<BrokeredMessage> bmList = new List<BrokeredMessage>();
  long i = 0;  
  while (i < count)
  {
   dlIE = subsciptionClient.PeekBatch(Convert.ToInt32(count));
   bmList.AddRange(dlIE);
   i = i + dlIE.Count();
  }

指導してくれたMikeWoに感謝

注:一度に表示できるメッセージの数には、ある種のサイズ制限があるようです。さまざまなサブスクリプションで試してみましたが、フェッチされるメッセージの数はそれぞれ異なりました。

于 2015-10-19T12:21:52.617 に答える
2

あなたが書いているトピックは偶然に分割されていますか? パーティション化されたエンティティからメッセージを受信すると、一度に 1 つのパーティションからのみフェッチされます。MSDN から:

"クライアントがパーティション分割されたキューまたはパーティション分割されたトピックのサブスクリプションからメッセージを受信する場合、Service Bus はメッセージのすべてのフラグメントをクエリし、メッセージ ストアのいずれかから返された最初のメッセージをレシーバーに返します。サービスBus は他のメッセージをキャッシュし、追加の受信要求を受信するとそれらを返します. 受信クライアントは、パーティション化 (パーティション化されたキューまたはトピックのクライアント側の動作 (たとえば、読み取り、完了、延期、deadletter、プリフェッチ)) を認識しません。通常のエンティティの動作と同じです。」

パーティション化されていないエンティティであっても、Receive メソッドまたは Peek メソッドのいずれかを使用して一度にすべてのメッセージを取得できると想定するのは、おそらくお勧めできません。特にメッセージのサイズが適切であるか、サイズが不確定である場合は、メッセージをはるかに小さなバッチでループ処理する方がはるかに効率的です。

実際にはキューからメッセージを削除したくないので、ReceiveBatch の代わりに PeekBatch を使用することを勧めします。これにより、メッセージのコピーを取得でき、ロックされません。同じ SubscriptionClient を PeekBatch と組み合わせて使用​​するループを強くお勧めします。内部で PeekBatch を使用して同じ SubscriptionClient を使用することにより、最後にプルされたシーケンス番号が保持され、ループを追跡してキュー全体を通過する必要があります。これにより、基本的にキュー全体を読み取ることができます。

于 2015-10-19T11:07:40.170 に答える