我们在项目中使用服务总线队列。当管理员选择清除队列时,我们需要一种功能来从队列中删除所有消息。我在网上搜索但找不到任何在QueueClient
类中执行此操作的函数。
我是否必须逐个弹出所有消息,然后将其标记为完成以清除队列或者是否有更好的方法?
QueueClient queueClient = _messagingFactory.CreateQueueClient(
queueName, ReceiveMode.PeekLock);
BrokeredMessage brokeredMessage = queueClient.Receive();
while (brokeredMessage != null )
{
brokeredMessage.Complete();
brokeredMessage = queueClient.Receive();
}
答案 0 :(得分:8)
在while循环中使用Receive()
方法会导致代码在队列为空时无限期运行,因为Receive()
方法将等待队列中出现另一条消息
如果您希望自动运行此功能,请尝试使用Peek()
方法。
例如:
while (queueClient.Peek() != null)
{
var brokeredMessage = queueClient.Receive();
brokeredMessage.Complete();
}
你可以使用hocho提到的ReceiveMode.ReceiveAndDelete
再次使这个更简单。
答案 1 :(得分: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);
}
答案 2 :(得分:2)
对于Azure-ServiceBus-Queues,有一个ReceiveBatch
-method,允许您在当时接收一批 n -messages。结合ReceiveMode.ReceiveAndDelete
,您可以更有效地清除队列。
警告可能会返回消息的数量 n ,但无法保证。此外,邮件批量大小限制为256K。
答案 3 :(得分:2)
清理Azure ServiceBus队列的最快方法是设置一个非常短的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;
答案 4 :(得分:2)
我使用ReceiveAndDelete,PrefetchCount,ReceiveBatchAsync和简单的真值循环组合而不是使用Peek,获得了良好的效果。下面的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包。
答案 5 :(得分:1)
如果您使用的是来自nuget的WindowsAzure.Storage库,则可以使用简单的Clear()
方法清除整个队列。我使用该库中的Microsoft.Windows.Azure.Queue
类来管理队列。否则,您可以通过其API per their documentation进行访问。我不知道该方法在Azure库中存在了多长时间,并且在最初询问问题时它可能不存在,但REST API至少从2014年this Azure feedback post < / p>
使用Azure库清除队列的完整.NET代码是:
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();
答案 6 :(得分:1)
您可以简单地从 azure 门户进行操作。
如果您不担心过去 14 天(默认)存储的队列消息并想立即清除队列,那么 -
将 message time to live 值更改为 5 或 10 秒并等待 5-10 秒。所有队列消息将被清除。您可以再次重置原始值。默认为 14 天。
答案 7 :(得分:0)
当我读到这个问题时,我首先想到的是为什么不删除并重新创建队列?这可能是一种方法。但如果不想这样做,您可以接收和删除每条消息,直到没有消息为止。
对于这两种方法,您都可以使用最新的 Azure 服务总线 .NET 库 Azure.Messaging.ServiceBus。
AdministrationClient
删除和重新创建队列using Azure.Messaging.ServiceBus.Administration;
ServiceBusAdministrationClient adminClient = new ServiceBusAdministrationClient("<connectionstring>");
await adminClient.DeleteQueueAsync("myqueue");
await adminClient.CreateQueueAsync("myqueue");
注意:ServiceBusAdministrationClient
用于已现有服务总线命名空间上的 CRUD 操作。如果您还需要能够创建命名空间,请改用 Microsoft.Azure.Management.ServiceBus 库。
using Azure.Messaging.ServiceBus;
await using var client = new ServiceBusClient("<connectionstring>");
ServiceBusReceiver receiver = client.CreateReceiver("myqueue",
new ServiceBusReceiverOptions { ReceiveMode = ServiceBusReceiveMode.ReceiveAndDelete });
while ((await receiver.PeekMessageAsync()) != null)
{
// receive in batches of 100 messages.
await receiver.ReceiveMessagesAsync(100);
}
ReceiveMode = ServiceBusReceiveMode.ReceiveAndDelete
是不言自明的。默认接收模式是 PeekLock
,它实际上并不从队列中删除消息 - 它告诉服务总线接收客户端想要显式 settle 接收到的消息。锁定部分意味着竞争接收者在锁定期间无法访问消息。