2012-03-29 56 views
18

我们在我们的项目中使用服务巴士队列。当管理员选择清除队列时,我们需要一种功能来删除队列中的所有消息。我在网上搜索,但无法找到QueueClient课程中的任何功能。一次性清除蔚蓝服务巴士队列

我是否必须逐个弹出所有消息,然后标记它们以清除队列或者是否有更好的方法?

QueueClient queueClient = _messagingFactory.CreateQueueClient(
           queueName, ReceiveMode.PeekLock); 

BrokeredMessage brokeredMessage = queueClient.Receive(); 

while (brokeredMessage != null) 
{ 
    brokeredMessage.Complete(); 
    brokeredMessage = queueClient.Receive(); 
} 
+1

我最近面临同样的问题,删除和重新创建不是循环工作的一个选项,但速度很慢,但是,使用'QueueClient'的'PrefetchCount'成员,您可以轻松地批量处理几千条消息往返,极大地加速了事情:http://msdn.microsoft.com/en-us/library/microsoft.servicebus.messaging.queueclient.prefetchcount.aspx – Necrolis 2013-12-20 21:29:59

回答

8

使用while循环中的Receive()方法好像你是会导致一旦队列为空,你的代码运行下去,因为Receive()方法将等待另一条消息出现在队列中。

如果您希望自动运行,请尝试使用Peek()方法。

例如:

while (queueClient.Peek() != null) 
{ 
    var brokeredMessage = queueClient.Receive(); 
    brokeredMessage.Complete(); 
} 

您可以用ReceiveMode.ReceiveAndDelete使这个再简单,因为被hocho提及。

+1

有几点值得关注:(1)Peek将得到预定,未来接收的消息不会导致您的应用挂起等待预定的消息。 (2)每个Peek移动到下一个消息,而不管它的状态如何,所以如果你放弃了第一个消息而不是Complete,第二个Peek将得到第二个消息,但第二个接收将重新处理第一个消息。这会导致Peek从接收消息中偏移一个消息,并会在每个放弃的消息的队列末尾留下一个未处理的消息。 – 2016-10-18 17:04:33

+0

+1 @JustinJStark对未收到新消息的队列测试此代码(按原样,不处理,仅接收并完成),它始终未能完全清除队列。它只清除了50-75%的信息。我不会使用这种方法来清除队列。 – Justin 2017-08-05 18:08:39

2

对于Azure-ServiceBus-Queues,有一个ReceiveBatch-method,它允许您在当时收到一批n-消息。结合ReceiveMode.ReceiveAndDelete,您可以更有效地清除队列。

买者消息的数量ň有可能被退还,但它不能保证。此外,邮件批量大小256K也有限制。

5

使用:

你可以写空服务总线队列或主题的方法/订阅:

MessageReceiver messageReceiver = ... 
while (messageReceiver.Peek() != null) 
{ 
    // Batch the receive operation 
    var brokeredMessages = messageReceiver.ReceiveBatch(300); 

    // Complete the messages 
    var completeTasks = brokeredMessages.Select(m => Task.Run(() => m.Complete())).ToArray(); 

    // Wait for the tasks to complete. 
    Task.WaitAll(completeTasks); 
} 
1

清理Azure Serv的最快方法iceBus队列是设置很短的DefaultMessageTimeToLive,等待几秒钟,尝试从队列中接收它强制更新,然后恢复最初的DefaultMessageTimeToLive

您可以从门户或代码做到这一点:

var namespaceManager = NamespaceManager.CreateFromConnectionString(connectionString); 
var queueDescription = _namespaceManager.GetQueue(queueName); 
var queueClient = QueueClient.CreateFromConnectionString(connectionString, queueName, ReceiveMode.ReceiveAndDelete); 

var dl = queueDescription.EnableDeadLetteringOnMessageExpiration; 
var ttl = queueDescription.DefaultMessageTimeToLive; 

queueDescription.EnableDeadLetteringOnMessageExpiration = false; 
queueDescription.DefaultMessageTimeToLive = TimeSpan.FromSeconds(1); 

Thread.Sleep(5000); 
var dumy = queueClient.ReceiveBatch(200, TimeSpan.FromSeconds(1)).ToArray(); 

queueDescription.EnableDeadLetteringOnMessageExpiration = dl; 
queueDescription.DefaultMessageTimeToLive = ttl; 
+0

嗨Florent,不知道如果API改变了,但我只是在我的队列中尝试了这一点,它没有变化。在队列之前和之后的相同消息。 – 2016-08-16 22:16:31

0

有一个简单的方法Clear()如果您使用的是WindowsAzure.Storage库从的NuGet清除整个队列。我使用该库中的Microsoft.Windows.Azure.Queue类来管理队列。否则,您可以通过他们的API per their documentation访问。我不知道该方法在Azure库中存在多久,并且在最初询问问题时可能不存在,但REST API至少源于2014年每个this Azure feedback post

完整。.NET代码清除队列在Azure库:

string connectionString = "YourAzureConnectionStringHere"; 
string queueName = "YourWebJobQueueName"; 
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(connectionString); 

// Create the queue client, then get a reference to queue 
CloudQueueClient queueClient = storageAccount.CreateCloudQueueClient(); 
queue = queueClient.GetQueueReference(GetQueueName(queueName)); 

// Clear the entire queue 
queue.Clear(); 
0

我有很好的效果使用ReceiveAndDeletePrefetchCountReceiveBatchAsync组合,和一个简单的道理循环,而不是使用偷看。实施例下面MessagingFactory:

var receiverFactory = MessagingFactory.CreateFromConnectionString("ConnString"); 
var receiver = receiverFactory.CreateMessageReceiver("QName", ReceiveMode.ReceiveAndDelete); 
receiver.PrefetchCount = 300; 

bool loop = true; 
while (loop) 
{ 
    var messages = await receiver.ReceiveBatchAsync(300, TimeSpan.FromSeconds(1)); 
    loop = messages.Any(); 
} 

仅需要WindowsAzure.ServiceBus NuGet包。