问题
When I use the following:
var deadLetterPath = SubscriptionClient.FormatDeadLetterPath(topicPath,subName);
var client = SubscriptionClient.CreateFromConnectionString(connectionString, deadLetterPath, subName);
I get an InvalidOperationException
Cannot directly create a client on a sub-queue. Create a client on the main queue and use that to create receivers on the appropriate sub-queue
Some parts of the azure documentation say to use SubscriptionClient.CreateReceiver to access a sub-queue but that method doesn't exist.
回答1:
Does this approach work for you ?
MessagingFactory factory = MessagingFactory.CreateFromConnectionString(cnxString);
var deadLetterPath = SubscriptionClient.FormatDeadLetterPath(topicPath,subName);
var dlqReceiver = factory.CreateMessageReceiver(deadLetterPath, ReceiveMode.ReceiveAndDelete);
I haven't test it out here (in a meeting), but give it a try
cheers
回答2:
There is a convention naming for Dead letter queue using Azure Service Bus:
- For Service Bus Queue: queuePath/$DeadLetterQueue
- For Service Bus Subscription: topicPath/subscriptionName/$DeadLetterQueue
So you can access your dead letter queues the same way you access your queues.
From @SamVanhoutte answer, you can see that the ServiceBus framework provides methods to format the dead letter queue name:
For Service Bus Queue:
QueueClient.FormatDeadLetterPath(queuePath)
For Service Bus Subscription:
SubscriptionClient.FormatDeadLetterPath(topicPath, subscriptionName)
I wrote two small methods to create a message receiver for queue and subscription where you can set if you want the deal letter queue or not:
/// <summary>
/// Create a new <see cref="MessageReceiver"/> object using the specified Service Bus Queue path.
/// </summary>
/// <param name="connectionString">The connection string to access the desired service namespace.</param>
/// <param name="queuePath">The Service Bus Queue path.</param>
/// <param name="isDeadLetter">True if the desired path is the deadletter queue.</param>
public static MessageReceiver CreateMessageReceiver(string connectionString, string queuePath,
bool isDeadLetter = false)
{
return MessagingFactory.CreateFromConnectionString(connectionString)
.CreateMessageReceiver(isDeadLetter
? QueueClient.FormatDeadLetterPath(queuePath)
: queuePath);
}
/// <summary>
/// Create a new <see cref="MessageReceiver"/> object using the specified Service Bus Topic Subscription path.
/// </summary>
/// <param name="connectionString">The connection string to access the desired service namespace.</param>
/// <param name="topicPath">The Service Bus Topic path.</param>
/// <param name="subscriptionName">The Service Bus Topic Subscription name.</param>
/// <param name="isDeadLetter">True if the desired path is the deadletter subqueue.</param>
public static MessageReceiver CreateMessageReceiver(string connectionString, string topicPath,
string subscriptionName, bool isDeadLetter = false)
{
return MessagingFactory.CreateFromConnectionString(connectionString)
.CreateMessageReceiver(isDeadLetter
? SubscriptionClient.FormatDeadLetterPath(topicPath, subscriptionName)
: SubscriptionClient.FormatSubscriptionPath(topicPath, subscriptionName));
}
回答3:
If you are using Microsoft.Azure.ServiceBus
instead of Microsoft.ServiceBus
, it is slightly different.
var deadQueuePath = EntityNameHelper.FormatDeadLetterPath(your_queue_name);
var deadQueueReceiver = new MessageReceiver(connectionString, deadQueuePath);
As per EntityNameHelper
class in Microsoft.Azure.ServiceBus
namespace, for topics, use the subscription path instead of your_queue_name.
The name of the queue, or path of the subscription.
/// <summary>
/// Formats the dead letter path for either a queue, or a subscription.
/// </summary>
/// <param name="entityPath">The name of the queue, or path of the subscription.</param>
/// <returns>The path as a string of the dead letter entity.</returns>
public static string FormatDeadLetterPath(string entityPath)
{
return EntityNameHelper.FormatSubQueuePath(entityPath, EntityNameHelper.DeadLetterQueueName);
}
回答4:
Those who want to do it in python.
Receive the messages from the dead letter queue:
from azure.servicebus import ServiceBusClient
import json
connectionString = "Your Connection String to Service Bus"
serviceBusClient = ServiceBusClient.from_connection_string(connectionString)
queueName = "Your Queue Name created in the Service Bus"
queueClient = serviceBusClient.get_queue(queueName)
with queueClient.get_deadletter_receiver(prefetch=5) as queueReceiver:
messages = queueReceiver.fetch_next(timeout=100)
for message in messages:
# message.body is a generator object. Use next() to get the body.
body = next(message.body)
message.complete()
Hope it helps to someone.
来源:https://stackoverflow.com/questions/22681954/how-do-you-access-the-dead-letter-sub-queue-on-an-azure-subscription