Azure Service Bus, as one of the most powerful and flexible messaging services, has become a cornerstone in the creation of highly reliable and scalable applications. This article aims to provide an in-depth understanding of Azure Service Bus, its implementation using .NET and C#, and how it can be leveraged to facilitate asynchronous messaging patterns between applications.
What Is Azure Service Bus
Azure Service Bus is a fully managed enterprise message broker with message queues and publish-subscribe topics. Service Bus is used to decouple applications and services from each other, providing the following benefits:
- Load-balancing work across competing workers
- Safely routing and transferring data and control across service and application boundaries
- Coordinating transactional work that requires a high-degree of reliability
It acts as a message broker, offering message queues and publish-subscribe topics within a namespace. It provides several benefits, such as load balancing, safe routing, and transaction coordination. Data transfer between applications and services is accomplished using messages. These messages, decorated with metadata, can carry any kind of information, including structured data encoded in common formats like JSON, XML, Apache Avro, or plain text.
Azure Service Bus supports various messaging scenarios:
Messaging: Facilitates the transfer of business data like sales orders, purchase orders, etc.
Decoupling Applications: Helps enhance application reliability and scalability.
Load Balancing: Allows multiple consumers to read from a queue simultaneously.
Topics and Subscriptions: Enables one-to-many relationships between publishers and subscribers.
Transactions: Supports several operations within the scope of an atomic transaction.
Message Sessions: Provides a mechanism for grouping related messages.
Azure Service Bus Concepts
When working with Azure Service Bus, there are several concepts to be aware of:
Queues: Messages are sent to and received from queues, which store the messages until the receiving application is ready to process them. Queues are useful in point-to-point communication scenarios. Only one consumer can receive and process a message from a queue.
Topics: Messages can also be sent and received via topics, which are useful in publish/subscribe scenarios. Unlike queues, topics can have multiple subscriptions, each of which can have multiple consumers. Each subscription receives a copy of every message sent to the topic.
Subscriptions: Subscriptions allow consumers to receive a copy of each message sent to a topic. They can have filters and actions to select and modify messages.
Namespaces: A namespace is a container for all messaging components. It can have multiple queues and topics and often serves as an application container. If you want to use Service Bus, you must first create a namespace.
Using Azure Service Bus In .NET
There is a client library for Azure Service Bus that can be used to send and receive messages. The library is available as a NuGet package, and it can be installed using the following command:
dotnet add package Azure.Messaging.ServiceBus
Creating A Service Bus Client
Once you have installed the package you can create a Service Bus client using the following code:
const string connectionString = "<connection-string>";
var client = new ServiceBusClient(connectionString);
If you are going to host your service on Azure, I highly recommend using Managed Identity to authenticate with Azure Service Bus.
In order to send messages, you need to use an instance of the
ServiceBusSender class. You can create an instance of this class using the
CreateSender method of the
var sender = client.CreateSender("<queue-name>");
ServiceBusSender class provides many methods for sending messages, including sending a batch of messages, sending delayed messages etc. For more information, check out the documentation. The following code shows how to send a single message:
var message = new ServiceBusMessage("Hello World!");
Note: The ServiceBusSender is safe to cache and use for the lifetime of an application or until the ServiceBusClient that it was created by is disposed. Caching the sender is recommended when the application is publishing messages regularly or semi-regularly.
In order to receive messages, you need to use an instance of the
ServiceBusReceiver class. You can create an instance of this class using the
CreateReceiver method of the
var receiver = client.CreateReceiver("<queue-name>");
To receive messages, you can use the
ReceiveMessageAsync method of the
var message = await receiver.ReceiveMessageAsync();
var body = message.Body.ToString();
Once you are done processing a message, there are options you have available to handle the message:
- Complete: This will remove the message from the queue or subscription. You call the
CompleteMessageAsyncmethod of the
ServiceBusReceiverclass to complete a message.
- Abandon: This will abandon the message and make it available to be received again. You call the
AbandonMessageAsyncmethod of the
ServiceBusReceiverclass to abandon a message.
- Defer: Deferring a message will prevent it from being received again using the standard receive methods. Instead, you need to use the
ReceiveDeferredMessageAsyncto receive deferred messages.
- Dead-letter: Dead lettering a message moves it to a sub-queue of the original queue, preventing the message from being received again. You need a receiver scoped to the dead letter queue to receive messages from the dead letter queue.
Service Bus Processor
ServiceBusProcessor class provides an abstraction around a set of ServiceBusReceiver that allows using an event based model for processing received
ServiceBusReceivedMessage. It is constructed by calling
CreateProcessor(String, ServiceBusProcessorOptions) on the service bus client. Here is an example of how to use it:
var processor = client.CreateProcessor("<queue-name>");
processor.ProcessMessageAsync += MessageHandler;
processor.ProcessErrorAsync += ErrorHandler;
static async Task MessageHandler(ProcessMessageEventArgs args)
var body = args.Message.Body.ToString();
static Task ErrorHandler(ProcessErrorEventArgs args)
When using the
ServiceBusProcessor, you won’t need to manually fetch messages from the queue. The processor will automatically fetch messages and call the
ProcessMessageAsync event handler. The
ProcessErrorAsync event handler will be called if there is an error while processing the message.
In this post, we looked at how to use Azure Service Bus in .NET. We looked at how to create a Service Bus client, how to send and receive messages, and how to use the Service Bus processor. I hope you found this post useful. If you have any questions or comments, please leave a comment below.