In the previous chapter, we briefly discussed key Azure services that are used to build resilient, scalable, and secure cloud native solutions. Many of these solutions leverage the power of message brokers to enable inter-application or service communication in an asynchronous manner. There are many such messaging systems available, including Apache Kafka, RabbitMQ, Azure Service Bus, ActiveMQ, and Amazon MQ. The focus of this chapter is to build decoupled solutions using Azure Service Bus, which is the enterprise-grade messaging solution offered by Microsoft Azure.
We will explore the key concepts and features of Azure Service Bus by building solutions using ASP.NET Core Web API for a fictional dental clinic to schedule appointment notifications for patients in a Service Bus Queue. The solution will be able to schedule a message for a future date as well as cancel it if the message has not been enqueued or has not been processed yet.
Introduction to Azure Service Bus
Features of Azure Service Bus
Getting started with Azure Service Bus: Queue and Topic
Provision an Azure Service Bus instance
Build an ASP.NET 6 Web API to send messages to Azure Service Bus Queue
After studying this chapter, you should have a solid grasp of the fundamentals of Azure Service Bus, as well as cloud services on Azure.
Introduction to Azure Service Bus
Enterprise messaging software, also known as message-oriented middleware, has been in existence since the late 1980s. Message-oriented middleware is a concept that involves the passing of data between applications using a communication channel that delivers messages from the sender to the receiver. These messages are transferred in an asynchronous manner between the sender and receiver using a message broker. These kinds of messaging systems help in decoupling applications and keeping the sender and receiver anonymous from each other. Azure Service Bus is one such messaging solution offered by Microsoft Azure as part of its cloud suite.
Azure Service Bus is an enterprise-grade, multitenant cloud messaging service of Microsoft Azure. It is a Platform-as-a-Service (PaaS) offering of Azure and is fully managed by Microsoft. As developers, we don’t need to worry about tasks such as handling of backups or hardware failures for the services because Azure takes care of it for us. Azure Service Bus supports point-to-point message delivery with Queues and message broadcasting using the publisher-subscriber model with Topics. In a later section of the chapter, we are going to briefly discuss Azure Service Bus Queues and Topics.
Azure Service Bus allows applications to interact or transfer data with each other using messages. It provides an excellent mechanism to build decoupled solutions and make them more scalable, reliable, and resilient. The producer should not be impacted due to the unavailability of the consumer. It supports data in different formats, such as JSON, XML, plain text, and so on, and provides client libraries in different languages to build solutions using it. Apart from that, it offers various advanced features such as message deferral, duplicate detection, and auto-forwarding, to name a few.
When to Use Azure Service Bus
Increasing scalability of the application
Replacing RPCs
Integrating heterogeneous applications
Reducing the coupling between applications
There are many additional scenarios where Azure Service Bus can be handy to use. Let’s discuss how Service Bus can help in the case of heterogeneous applications.
Suppose we have two applications, Application A and Application B. Application A is written in Java while Application B is written in Python. To fulfill some requirements, we want to establish communication between these applications.
Normally, this would be really difficult to do between two applications written in different languages unless you have a common medium of communication between them.
Service Bus helps us do so without a lot of trouble. Service Bus provides clients for multiple languages, including .Net, Python, Ruby, and many more, which helps in sending messages between heterogeneous applications via its message broker.
Features of Azure Service Bus
Message filtering
Message sessions
Message auto-forwarding
Duplicate detection
Message expiration
Message deferral
Message batching
Let’s explore each of these features in detail.
Message Filtering
Azure Service Bus supports message filtering with Topics. It is supported with queues. You can configure subscription rules for Azure Service Bus Topics to deliver messages categorically to different subscribers as per the business requirements. A subscription rule can consist of filter condition or actions. To learn more about the message filtering feature of Azure Service Bus, take a look at https://docs.microsoft.com/en-us/azure/service-bus-messaging/topic-filters.
Message Sessions
Azure Service Bus provides a guaranteed reliable delivery of related messages in a particular sequence to the receiver/subscriber application by using message sessions. To leverage this feature, you will have to enable sessions while creating queues/topics. While sending a message to the queue/topic as part of a session, the sender application will also have to set the session ID property. This will help the receiver application to distinguish if a particular message is associated with a particular session or not. To learn more about message sessions of Azure Service Bus, check out https://docs.microsoft.com/en-us/azure/service-bus-messaging/message-sessions.
Message Auto-forwarding
Azure Service Bus provides a way to send messages from a particular queue or subscription to another queue or topic within the namespace for the purpose of chaining them. Any messages coming to our source queue/subscription will be removed and moved to the destination queue/topic automatically.
Duplicate Detection
In certain scenarios, a message sent by the sender application may not get delivered within a certain time period, because of which the sender application might resend the message to the service bus queue to be picked up by the receiver application for further processing. Now our receiver application will be processing the same message twice because of the message being resent by the sender. To remove such duplicate messages, Azure Service Bus provides a duplicate detection feature that discards the duplicate message for us.
Message Expiration
While solving real-world problems, we often come across scenarios where the time to live of a message is crucial for the sanity of the message. Some messages can be of no value after a certain threshold. For example, if a notification of an EMI payment to the customer is sent after the due date, it does not add any business value and may result in a bad customer experience. To avoid such scenarios, Azure Service Bus provides a feature to define the maximum time to live of messages for a queue or topic while we are provisioning them.
Message Deferral
Whenever you send a message to a message broker, it gets enqueued in a queue or topic and is available for the receiver application to pick up the message and process it further. But in some scenarios where you might want to schedule a message to be processed at a later date. Azure Service Bus provides a message deferral mechanism to address this scenario. You can schedule a message to be sent at a future date in the queue and the message will only get queued once the scheduled date has come. We are going on a use case for this feature and implement it later in the chapter.
Message Batching
Azure Service Bus provides a mechanism to batch a certain number of messages and send them in a batch to the receiver application to process at one go, which results in better utilization of resources at the receiver’s end.
Queues, Topics, and Namespaces
Queues
Topics
Namespaces
Queues
Topics
Namespaces
In Azure Service Bus, Namespaces acts as a logical container for all the queues and topics. To create any queues or topics in Azure Service Bus, you first have to provision an Azure Service Bus Namespace. The number of queues or topics that you can have in a namespace is dependent on the pricing tier that you select while provisioning the namespace.
Working with Azure Service Bus
Now that you have a general understanding of what Azure Service Bus is and what are its key features and components, let’s create an Azure Service Bus Queue instance in Azure Portal, a simple message sender application, and a web API to schedule appointments for our fictional dental clinic.
Create an Azure Service Bus Namespace in Azure Portal
Create an Azure Service Bus Namespace in Azure Portal
Create an SAS Policy to Access the Azure Service Bus Namespace
To access or interact with Azure Service Bus Queues or Topics from our application, we need to authenticate our application’s request to the service bus. This can be done in different ways, such as using Azure Active Directory (Azure AD)–based authentication or SAS policies. For the purpose of this book, we will be using SAS policies. For enterprise applications, it is recommended to use Azure AD–based authentication or managed identity if the applications are deployed inside Azure in an Azure Function or App Service by providing necessary role-based access control (RBAC) permissions to the service bus instance.
Create a Console App to Send Messages to Azure Service Bus Queue
Program.cs
Create a Web API to Schedule Messages in Azure Service Bus Queue
In the previous section, you learned ways to send messages to the Azure Service Bus queue from your console application. This section focuses on solving the need of a fictional dental clinic to send appointment notifications to its patients. The dental clinic currently has a worker process in place that picks up messages from the service bus queue and processes them to send notifications. Currently, the worker process is processing any messages that are available in the queue, but the clinic doesn’t want the worker to send the notification until the right time. The notifications should be sent only three hours before the appointment time. Thus, the message cannot be sent to the queue directly. To solve this problem, we need to build a solution to schedule a message—an appointment reminder in this case—three hours before the appointment time so that the message enqueues in the queue at the scheduled time and then the worker process picks it up to process it and sends the notification to the patient.
We will be building an ASP.NET Core Web API to solve this problem by scheduling messages in the service bus queue by using the message deferral feature of Azure Service Bus. Our web API will provide two essential features: schedule a message to the service bus queue and cancel a scheduled message. There can be business scenarios where a patient can cancel a scheduled appointment and reschedule it for a future date. In such scenarios, the cancel feature will be essential, as we will have to cancel the existing scheduled message because it is no longer valid and may cause a bad customer experience.
Visual Studio will create a sample API project for us that contains a simple WeatherForecastController, which returns randomly generated weather data to the client. Remove the WeatherForecastController.cs and WeatherForecast.cs files from our project, because we don’t need them.
For the time being, we are done with the program.cs file of our project. Let’s create two folders in our project: Business and Models. The Business folder will contain our interface and the classes implementing them. The Models folder will contain the classes of our data models.
In the preceding code snippet, we are leveraging the ServiceBusClient that we had injected in the DI container in our program.cs file and we are using it to instantiate the _serviceBusSender client to interact with the Azure Service Bus Queue whose name is stored with the key name as queueName in our appsetting.json file.
Now let’s implement the methods of the INotificationBusiness interface in the class. Let’s add the following code snippet to implement the methods.
The ScheduleAppointmentNotification converts the appointment object coming in the parameter of the method to a string type and then converts it into a service bus message. Then we calculate the time when we want to schedule it by subtracting three hours from the value passed in the ScheduledAt property of our appointment object in the parameter of our method and store it in the enqueueTime variable. It might be confusing at first glance when you see that enqueueTime will have three hours subtracted while we are using the AddHours method. It is happening as such because the value of enqueueDifference in our appsettings.json file is -3. We then use the ScheduleMessageAsync method of the ServiceBusSender client to schedule the message by passing our serviceBusMessage and enqueueTime as parameters. This method returns the sequence number of the scheduled message in the service bus queue.
The CancelAppointmentNotification method takes a long value (i.e., messageSequenceNumber) as a parameter and then uses the CancelScheduledMessageAsync method of the serviceBusSender client to cancel the method.
Let’s add our actions in our AppointmentController. We are going to have two actions: ScheduledAppointmentNotificationInQueue and CancelAppointmentNotificationFromQueue.
URL route: http://localhost:5010/api/Appointment/Notification/schedule
HTTP verb: POST
URL route: http://localhost:5010/api/Appointment/Notification/Cancel/{messageSequenceNumber}
HTTP verb: DELETE
And with this our API project to schedule notifications for our fictional dental clinic is complete. Press Ctrl+F5 to build and run our project. The complete source code of this API project can be found at the following GitHub repository: https://github.com/AshirwadSatapathi/DentalAppointments.
In the next section, we will test our API using Postman, which is an API testing tool.
Test APIs Using Postman
Summary
Azure Service Bus is one of the most widely used cloud messaging services used by Microsoft Azure. It is a PaaS offering of Microsoft that helps us get rid of the hassles associated with infrastructure provisioning and maintenance of our messaging systems. Azure Service Bus provides rich support for SDKs in various languages like Node.js, Python .NET, Java, and forth. It supports protocols like Advanced Message Queuing Protocol (AMQP) and HTTPREST. It provides us two styles of messaging: point-to-point with Queues and publish-subscribe with Topics. In this chapter, you learned ways to provision an Azure Service Bus Namespace and Queue in Azure Portal. You learned how to develop a console app to send messages to the Azure Service Bus queue using a connection string. And finally, we built a set of APIs to schedule and cancel messages to solve the problem of our fictional dental clinic. During this process, you learned ways to leverage the Azure Service Bus SDK for .NET to build applications by implementing the message deferral feature of Service Bus.