Service Bus is a high throughput, reliable message queue serivce. Messages can be stored until read, and there are advanced features like a dead-message queue for messages which were never delivered, or failed processing. You can use Service Bus queues to support the standard messaging patterns.
In this lab we’ll use a fire-and-forget messaging pattern, where a publisher sends messages without expecting a return, or even knowing which component will process them.
The Service Bus resource you create is a namespace, which is a grouping construct for multiple queues. Create a new resource in the Portal and search for ‘service bus’. Click to create a Service Bus resource - this is actually the namespace. Explore the options:
.servicebus.windows.net
Create a namespace with the CLI:
We’ll switch to the CLI now. Create a Resource Group for the lab:
az group create -n labs-servicebus --tags courselabs=azure -l westeurope
📋 Create a namespace with a servicebus namespace
command, using the Basic SKU.
Not sure how?</summary>
Check the help text:
az servicebus namespace create --help
Only name and RG are required, but the default SKU is Standard so we need to set that:
az servicebus namespace create -g labs-servicebus --location westeurope --sku Basic -n <sb-name>
</details>
The output includes service bus endpoint - comunication is over HTTPS
Open the Service Bus Namespace in the portal - you’ll see the usual blades, plus Queues and Shared access policies. Shared access tokens are used for authentication and authorization, similar to storage accounts, except there’s a one-to-one relationship between policies and tokens.
In the Basic SKU the only messaging option is a queue - create one to send and listen for messages:
az servicebus queue create -g labs-servicebus --name echo --namespace-name <sb-name>
Open the queue in the portal and you see metrics on message counts.
There’s also a Shared access policies tab at the queue level, so you can create fine-grained permissions for apps which need to send to one queue and read from another.
Subscribers listen on a queue in an infinite loop; when they receive a message they process it. In a distributed application you may have multiple components which each subscribe to different queues, and each component could have multiple instances.
Service Bus uses a standard protocol called Advanced Message Queuing Protocol AMQP. Other queue technologies implement the same protocol, so Service Bus can be used as a drop-in replacement for RabbitMQ and others.
We have a simple app which subscribes to the queue using the Service Bus client library:
Run the app locally (you’ll need the .NET 6 SDK), using a parameter to set the connection string:
# get the connection string for your queue:
az servicebus namespace authorization-rule keys list -n RootManageSharedAccessKey -g labs-servicebus --query primaryConnectionString -o tsv --namespace-name <sb-name>
# run the app:
dotnet run --project src/servicebus/subscriber -cs '<connection-string>'
The app will listen for messages until you shut it down.
We have another simple app which publishes messages to the queue in a loop - publishing a batch, waiting and then publishing another batch:
In a different console run the publisher app:
dotnet run --project src/servicebus/publisher -cs '<connection-string>'
You’ll see the publisher send messages and the subscriber receive them. In the portal you can see the metrics, but there aren’t many message being processed at the moment.
Check the number of the last batch processed by the subscriber, then end the subscriber (Ctrl-C or Cmd-C in the subscriber window) - leave the publisher app running.
The publisher keeps send messages. Wait for it to publish some more batches.
If you run the subscriber again, it might do one of three things:
📋 Run the subscriber. What does it actually do?
Not sure how?</summary>
It’s the same command:
dotnet run --project src/servicebus/subscriber -cs '<connection-string>'
You should see the subscriber pick up where it left off, processing the new batches that were published since you closed the previous instance of the subscriber.
</details>
Service bus queues store messages until they receive a completion acknowledgement.
New subscribers don’t get any messages which have been flagged as completed, but they do get all the un-completed messages in the queue. That way requests don’t get lost or processed twice if a subscriber fails.
Open another console and run another instance of the subscriber:
dotnet run --project src/servicebus/subscriber -cs '<connection-string>'
Now the subscribers share the messages - they take turns to receive a message (more-or-less). There’s no duplication, so instances can process their own set of messages.
Messaging is all about distributing work at scale. What happens when there are multiple publishers - how do the subscribers split the work?
Reliability is a key factor too. You can run the subscriber without acknowledging message completion using the -ack False
flag. If you only have a single subcriber which doesn’t acknowledge messages, and you quit and replace that subscriber, what happens to the messages it processed?
Delete the lab RG:
az group delete -y --no-wait -n labs-servicebus