December 2nd, 2020

Announcing the new Azure Service Bus Client Libraries

Richard Park
Developer

Version 7 of the Azure Service Bus packages have now been released (C#, Java, Python and JavaScript), following the new Azure SDK guidelines. These guidelines provide consistency across all Azure SDK client libraries while also allowing each language to follow the idioms for their respective languages.

This library is the result of months of development, design discussions, feedback, and observing developers in user studies as they worked with Azure Service Bus. In this release, we’ve also worked on adding tracing, better error classification to simplify error handling, and simplifying concepts to make them more approachable.

This post will cover some of our goals for the design of the new library and provide some background on the process that led us here.

Making It Easier To Receive Messages Forever

Reading an endless stream of messages is a common activity for applications working with Azure Service Bus. Many Service Bus programs have a structure much like this:

while (forever)
   get message
   process message (send to another service, update a database, etc...)

Our goal was to make it simple for users to write a robust and production-ready application, with built-in recovery and error handling.

In Java and .NET, this pattern is available via the ServiceBusProcessor. The ServiceBusProcessor (C# sample | Java sample) allows you to specify two callbacks – a ProcessMessages callback that will receive each message as it arrives in your queue or topic, and a ProcessError callback that will get called when things fail. In JavaScript, we offer this behavior using the ServiceBusReceiver (JavaScript sample). All of these message processors continue running until you explicitly stop them, recovering from network failures and handling reconnects.

Promoting Essential Concepts: Subqueues, Dead Lettering, and Poisoning

We spent quite a bit of time trying to think about the essential activities for developers working with Service Bus. Programs that use a messaging queue need to comprehend the concept of a poison message. A poison message is a message that will never succeed when processed. Usually, it’s the result of a malformed message (perhaps the body was a particularly big JSON message and was truncated).

When these messages get into message queues they can cause clogs in the system. Message handlers fail on poisoned messages, causing the message to be continually redelivered until it either expires or exceeds the delivery count. What people sometimes do not realize is that those messages are not just thrown away. They go into a special sub-queue that is associated with your queue or subscription – the dead letter queue.

Messages that are continually abandoned via your receiver or messages that you have explicitly dead lettered are stored there. Messages in the dead letter queue are good first indicators of problems and can help with troubleshooting. In systems where messages are processed and moved through several layers of queues or topics, a bad message can cause spiralling effects.

We wanted to make sure that people were aware that the dead letter queues existed and make it simple and obvious to access. We decided to approach this across several different areas:

  1. We improved our samples around dead letter queues. This helps people who start with the code first, rather than reading the documentation.
  2. We restructured the API across all languages to use the same technique for opening the dead letter queue. This makes it easier to adapt solutions from other languages.

The restructuring of the API was a bigger change than expected. The biggest problem was the number of ways that we had for opening a dead letter queue across the different SDKs. In .NET, we had a class called EntityNameHelper, which would allow you to take an entity path (name of queue, or the topic and subscription combined) and get the specially formatted entity name for a dead letter queue. In JavaScript, you had to create a Receiver to the queue first and from that receiver you could then create a dead letter receiver.

The EntityNameHelper concept was actually pretty popular when we first approached how to redesign this area. It’s simple (it’s just a method that takes the entity path parts and formats it, returning the result as a string) and it can help move some of the overloads we provide to address queues vs topics and subscriptions to another class.

However, user testing has shown us that people do not browse through the classes in a library to figure out what exists. If we don’t provide a nice tieback to the ServiceBusClient (the primary client for the package), then finding a stray utility class is difficult. Additionally, since the return type of the EntityNameHelper is just a string there isn’t a way to track back to the ServiceBusClient through the return type.

We have a design principle that states we should allow developers to build on their previous knowledge to learn additional concepts – having a person having to reset each time they want to try something else in our library would be a failure in our design. In this case we know that a user already understands the basic concept of creating a receiver. We can leverage that knowledge and add a small tweak to allow them to target these sub-queues:

// C#

// creating a normal receiver
ServiceBusReceiver receiver = client.CreateReceiver("queue");

// creating a receiver to a dead letter queue
ServiceBusReceiver receiver = client.CreateReceiver("queue", new ServiceBusReceiverOptions {
   SubQueue = SubQueue.DeadLetter
});

By offering this as an option we’ve also allowed for natural expansion as more subqueues are added in the future, with no additional impact to the user. Additionally, IDEs and editors are also able to allow the developer to explore the API using code completion, making discovery simple as well.

Making Sessions Simpler

As part of this latest release, we looked at Azure Service Bus Sessions and how to fit it into the new design. Sessions allow you to logically group messages within a queue or subscription.

Our design took into account two workflows for sessions: consuming groups of messages where the names of the sessions are not known in advance (for instance, processes sending messages about activity by a user) as well as consuming messages for a specified session ID (useful when implementing the request/response pattern).

The first pattern, of consuming a session with a known session id, was simple – just like addressing a queue, opening a named session is just another option parameter when creating a session receiver.

// JavaScript
serviceBusClient.acceptSession("queue", "session-id");

What we wanted was something to model this flow:

while sessions_available
   get next session
   process session messages til empty
   close session

On looking at this, we realized we already had a great pattern for this – the processor, as described in the earlier section: ServiceBusProcessor/ServiceBusReceiver.subscribe().

Rather that being concurrent on individual messages, we are instead concurrent at the session level. Multiple receivers are transparently opened and receive from mutiple sessions in parallel, with the same ease of use you’d expect from the processor. As another big benefit – we’ve already shown you how to use the processor for non-session-enabled queues, making this next step an incremental one, rather than a big leap.

We have some great samples to show you exactly how to implement this in your application:

Conclusion

Azure Service Bus is one of Azure’s core offerings, that can greatly simplify your application. The latest set of packages are our effort to make integrating Service Bus quick and painless, allowing you to quickly jumpstart your applications and get running.

For more information about each language from this article please see the following:

Azure SDK Blog Contributions

Thank you for reading this Azure SDK blog post! We hope that you learned something new and welcome you to share this post. We are open to Azure SDK blog contributions. Please contact us at azsdkblog@microsoft.com with your topic and we’ll get you set up as a guest blogger.

Azure SDK Links

Author

Richard Park
Developer

Developer on the Azure SDK, currently working on Go!

0 comments

Discussion are closed.