Azure Service Bus Messaging
Implement asynchronous messaging with Azure Service Bus.
By EMEPublished: February 20, 2025
azureservice busmessagingasyncqueuestopics
A Simple Analogy
Azure Service Bus is like the postal system for cloud applications. Messages are reliably delivered even if the recipient is temporarily unavailable.
Why Service Bus?
- Decoupling: Apps don't call each other directly
- Asynchronous: Don't wait for responses
- Reliable: Messages persist if app is down
- Scalable: Handle message spikes
- Ordering: Optional FIFO guarantees
Queue Operations
using Azure.Messaging.ServiceBus;
var connectionString = "Endpoint=sb://...";
var client = new ServiceBusClient(connectionString);
// Send message
var sender = client.CreateSender("order-queue");
var message = new ServiceBusMessage("Order #123 created")
{
ContentType = "application/json",
Subject = "OrderCreated",
CorrelationId = "order-123"
};
await sender.SendMessageAsync(message);
// Receive messages
var receiver = client.CreateReceiver("order-queue");
var receivedMessage = await receiver.ReceiveMessageAsync();
if (receivedMessage != null)
{
Console.WriteLine(receivedMessage.Body);
await receiver.CompleteMessageAsync(receivedMessage);
}
Topics and Subscriptions
// Publish to topic
var topicClient = client.CreateSender("orders-topic");
var message = new ServiceBusMessage("Order #123 created")
{
ApplicationProperties = { { "Type", "OrderCreated" } }
};
await topicClient.SendMessageAsync(message);
// Subscribe to topic
var receiver = client.CreateReceiver("orders-topic", "email-subscription");
var message = await receiver.ReceiveMessageAsync();
if (message != null)
{
Console.WriteLine("Email notification triggered");
await receiver.CompleteMessageAsync(message);
}
Message Processing
public class OrderProcessor
{
private readonly ServiceBusClient _client;
public async Task StartProcessingAsync()
{
var receiver = _client.CreateReceiver("orders-queue");
var options = new ServiceBusProcessorOptions
{
MaxConcurrentCalls = 10,
AutoCompleteMessages = false
};
var processor = _client.CreateProcessor("orders-queue", options);
processor.ProcessMessageAsync += MessageHandler;
processor.ProcessErrorAsync += ErrorHandler;
await processor.StartProcessingAsync();
}
private async Task MessageHandler(ProcessMessageEventArgs args)
{
try
{
var message = args.Message;
var body = message.Body.ToString();
// Process message
await ProcessOrderAsync(body);
// Complete message
await args.CompleteMessageAsync(message);
}
catch (Exception ex)
{
// Dead letter on error
await args.DeadLetterMessageAsync(args.Message);
}
}
private Task ErrorHandler(ProcessErrorEventArgs args)
{
Console.WriteLine($"Error: {args.Exception}");
return Task.CompletedTask;
}
}
Dead Letter Queue
// Messages automatically go to dead letter queue after max retries
var receiver = client.CreateReceiver("orders-queue");
// Access dead letter messages
var deadLetterReceiver = client.CreateReceiver(
"orders-queue",
new ServiceBusReceiverOptions { SubQueue = SubQueue.DeadLetter });
var deadLetterMessage = await deadLetterReceiver.ReceiveMessageAsync();
Console.WriteLine($"Reason: {deadLetterMessage.DeadLetterReason}");
Console.WriteLine($"Error: {deadLetterMessage.DeadLetterErrorDescription}");
Best Practices
- Use sessions: For correlated messages
- Set TTL: Messages expire
- Partition keys: Enable message ordering
- Dead letter: Handle poison messages
- Monitor: Track queue depth
Related Concepts
- Event Grid
- Event Hubs
- Logic Apps
- Message-driven architecture
Summary
Azure Service Bus provides reliable, scalable messaging for decoupled applications. Use queues for point-to-point and topics for pub/sub patterns.