Azure Service Bus is a highly-reliable cloud messaging service from Microsoft.
Use the client library @azure/service-bus
in your application to
- Send messages to an Azure Service Bus Queue or Topic
- Receive messages from an Azure Service Bus Queue or Subscription
- Create/Get/Delete/Update/List Queues/Topics/Subscriptions/Rules in an Azure Service Bus namespace.
Resources for @azure/service-bus
version 7:
Key links:
- Source code
- Package (npm)
- API Reference Documentation
- Product documentation
- Samples
- Troubleshooting Guide
NOTE: If you are using version 1.1.10 or lower and want to migrate to the latest version of this package please look at our migration guide to move from Service Bus V1 to Service Bus V7
Install the latest version for the Azure Service Bus client library using npm.
npm install @azure/service-bus
TypeScript users need to have Node type definitions installed:
npm install @types/node
You also need to enable compilerOptions.allowSyntheticDefaultImports
in your tsconfig.json. Note that if you have enabled compilerOptions.esModuleInterop
, allowSyntheticDefaultImports
is enabled by default. See TypeScript's compiler options handbook for more information.
To use this client library in the browser, first you need to use a bundler. For details on how to do this, please refer to our bundling documentation.
In addition to what is described there, this library also needs additional polyfills for the following NodeJS core built-in modules in order to work properly in the browsers:
buffer
os
path
process
If you are using Webpack v5, you can install the following dev dependencies
npm install --save-dev os-browserify path-browserify
then add the following into your webpack.config.js
const path = require("path");
+const webpack = require("webpack");
module.exports = {
entry: "./src/index.ts",
@@ -12,8 +13,21 @@ module.exports = {
},
],
},
+ plugins: [
+ new webpack.ProvidePlugin({
+ process: "process/browser",
+ }),
+ new webpack.ProvidePlugin({
+ Buffer: ["buffer", "Buffer"],
+ }),
+ ],
resolve: {
extensions: [".ts", ".js"],
+ fallback: {
+ buffer: require.resolve("buffer/"),
+ os: require.resolve("os-browserify"),
+ path: require.resolve("path-browserify"),
+ },
},
If you are using Rollup bundler, install the following dev dependencies
npm install --save-dev @rollup/plugin-commonjs @rollup/plugin-inject @rollup/plugin-node-resolve
Then include the following in your rollup.config.js
+import nodeResolve from "@rollup/plugin-node-resolve";
+import cjs from "@rollup/plugin-commonjs";
+import shim from "rollup-plugin-shim";
+import inject from "@rollup/plugin-inject";
export default {
// other configs
plugins: [
+ shim({
+ fs: `export default {}`,
+ net: `export default {}`,
+ tls: `export default {}`,
+ path: `export default {}`,
+ dns: `export function resolve() { }`,
+ }),
+ nodeResolve({
+ mainFields: ["module", "browser"],
+ preferBuiltins: false,
+ }),
+ cjs(),
+ inject({
+ modules: {
+ Buffer: ["buffer", "Buffer"],
+ process: "process",
+ },
+ exclude: ["./**/package.json"],
+ }),
]
};
Please consult the documentation of your favorite bundler for more information on using polyfills.
Similar to browsers, React Native does not support some JavaScript api used by this SDK library so you need to provide polyfills for them. Please see the Messaging React Native sample with Expo for more details.
Interaction with Service Bus starts with an instance of the ServiceBusClient class. You can authenticate to Service Bus using a connection string or using an Azure Active Directory credential.
This method takes the connection string to your Service Bus instance. You can get the connection string from the Azure portal.
const { ServiceBusClient } = require("@azure/service-bus");
const serviceBusClient = new ServiceBusClient("<connectionString>");
More information about this constructor is available in the API documentation.
Authentication with Azure Active Directory uses the Azure Identity library.
The example below uses the DefaultAzureCredential, one of many
available credential providers from the @azure/identity
library.
const { ServiceBusClient } = require("@azure/service-bus");
const { DefaultAzureCredential } = require("@azure/identity");
const fullyQualifiedNamespace = "<name-of-service-bus-namespace>.servicebus.windows.net";
const credential = new DefaultAzureCredential();
const serviceBusClient = new ServiceBusClient(fullyQualifiedNamespace, credential);
NOTE: If you're using your own implementation of the
TokenCredential
interface against AAD, then set the "scopes" for service-bus to the following to get the appropriate token:
["https://servicebus.azure.net//user_impersonation"];
More information about this constructor is available in the API documentation
Once you've initialized a ServiceBusClient
, you can interact with these resources within a
Service Bus Namespace:
- Queues: Allows for sending and receiving messages. Often used for point-to-point communication.
- Topics: As opposed to Queues, Topics are better suited to publish/subscribe scenarios. A topic can be sent to, but requires a subscription, of which there can be multiple in parallel, to consume from.
- Subscriptions: The mechanism to consume from a Topic. Each subscription is independent, and receives a copy of each message sent to the topic. Rules and Filters can be used to tailor which messages are received by a specific subscription.
For more information about these resources, see What is Azure Service Bus?.
To interact with these resources, one should be familiar with the following SDK concepts:
- Send messages, to a queue or topic, using a
ServiceBusSender
created usingServiceBusClient.createSender()
. - Receive messages, from either a queue or a subscription, using a
ServiceBusReceiver
created usingServiceBusClient.createReceiver()
. - Receive messages, from session enabled queues or subscriptions, using a
ServiceBusSessionReceiver
created usingServiceBusClient.acceptSession()
orServiceBusClient.acceptNextSession()
.
Please note that the Queues, Topics and Subscriptions should be created prior to using this library.
The following sections provide code snippets that cover some of the common tasks using Azure Service Bus
- Send messages
- Receive messages
- Settle a message
- Dead letter queues
- Send messages using Sessions
- Receive messages from Sessions
- Manage resources of a service bus namespace
- Additional samples
Once you have created an instance of a ServiceBusClient
class, you can get a ServiceBusSender
using the createSender method which you can use to send messages.
const sender = serviceBusClient.createSender("my-queue");
const messages = [
{ body: "Albert Einstein" },
{ body: "Werner Heisenberg" },
{ body: "Marie Curie" },
{ body: "Steven Hawking" },
{ body: "Isaac Newton" },
{ body: "Niels Bohr" },
{ body: "Michael Faraday" },
{ body: "Galileo Galilei" },
{ body: "Johannes Kepler" },
{ body: "Nikolaus Kopernikus" },
];
// sending a single message
await sender.sendMessages(messages[0]);
// sending multiple messages in a single call
// this will fail if the messages cannot fit in a batch
await sender.sendMessages(messages);
// Sends multiple messages using one or more ServiceBusMessageBatch objects as required
let batch = await sender.createMessageBatch();
for (let i = 0; i < messages.length; i++) {
const message = messages[i];
if (!batch.tryAddMessage(message)) {
// Send the current batch as it is full and create a new one
await sender.sendMessages(batch);
batch = await sender.createMessageBatch();
if (!batch.tryAddMessage(messages[i])) {
throw new Error("Message too big to fit in a batch");
}
}
}
// Send the batch
await sender.sendMessages(batch);
Once you have created an instance of a ServiceBusClient
class, you can get a ServiceBusReceiver
using the createReceiver method.
const receiver = serviceBusClient.createReceiver("my-queue");
There are two receiveMode
s available.
- "peekLock" - In peekLock mode, the receiver has a lock on the message for the duration specified on the queue.
- "receiveAndDelete" - In receiveAndDelete mode, messages are deleted from Service Bus as they are received.
If the receiveMode is not provided in the options, it defaults to the "peekLock" mode. You can also settle the messages received in "peekLock" mode.
You can use this receiver in one of 3 ways to receive messages:
Use the receiveMessages function which returns a promise that resolves to an array of messages.
const myMessages = await receiver.receiveMessages(10);
Use the subscribe method to set up message handlers and have it running as long as you need.
When you are done, call receiver.close()
to stop receiving any more messages.
const myMessageHandler = async (message) => {
// your code here
console.log(`message.body: ${message.body}`);
};
const myErrorHandler = async (args) => {
console.log(
`Error occurred with ${args.entityPath} within ${args.fullyQualifiedNamespace}: `,
args.error,
);
};
receiver.subscribe({
processMessage: myMessageHandler,
processError: myErrorHandler,
});
Use the getMessageIterator to get an async iterator over messages
for await (const message of receiver.getMessageIterator()) {
// your code here
}
Once you receive a message you can call completeMessage()
, abandonMessage()
, deferMessage()
or deadLetterMessage()
on the receiver based on how you want to settle the message.
To learn more, please read Settling Received Messages
The dead letter queue is a sub-queue. Each queue or subscription has its own dead letter queue. Dead letter queues store
messages that have been explicitly dead lettered (via receiver.deadLetterMessage()
), or messages that have exceeded
their maximum delivery count.
Creating a receiver for a dead letter sub-queue is similar to creating a receiver for a subscription or queue:
// To receive from a queue's dead letter sub-queue
const deadLetterReceiverForQueue = serviceBusClient.createReceiver("queue", {
subQueueType: "deadLetter",
});
// To receive from a subscription's dead letter sub-queue
const deadLetterReceiverForSubscription = serviceBusClient.createReceiver("topic", "subscription", {
subQueueType: "deadLetter",
});
// Dead letter receivers work like any other receiver connected to a queue
// ex:
const messages = await deadLetterReceiverForQueue.receiveMessages(5);
for (const message of messages) {
console.log(`Dead lettered message: ${message.body}`);
}
Full samples demonstrating dead letter queues more thoroughly:
- Using receiver.deadLetterMessage() to explicitly send messages to the dead letter sub-queue
- Receiving messages from the dead letter sub-queue
Using sessions requires you to create a session enabled Queue or Subscription. You can read more about how to configure this feature in the portal here.
In order to send messages to a session, use the ServiceBusClient
to create a sender using
createSender.
When sending the message, set the sessionId
property in the message to ensure
your message lands in the right session.
const sender = serviceBusClient.createSender("my-session-queue");
await sender.sendMessages({
body: "my-message-body",
sessionId: "my-session",
});
You can read more about how sessions work here.
Using sessions requires you to create a session enabled Queue or Subscription. You can read more about how to configure this feature in the portal here.
Unlike non-session-enabled Queues or Subscriptions, only a single receiver
can read from a session at any time. This is enforced by locking a session,
which is handled by Service Bus. Conceptually, this is similar to how message
locking works when using peekLock
mode - when a message (or session) is
locked your receiver has exclusive access to it.
In order to open and lock a session, use an instance of ServiceBusClient
to create a SessionReceiver.
There are two ways of choosing which session to open:
-
Specify a
sessionId
, which locks a named session.const receiver = await serviceBusClient.acceptSession("my-session-queue", "my-session");
-
Do not specify a session id. In this case Service Bus will find the next available session that is not already locked.
const receiver = await serviceBusClient.acceptNextSession("my-session-queue");
You can find the name of the session via the
sessionId
property on theSessionReceiver
. If the receiveMode is not provided in the options, it defaults to the "peekLock" mode. You can also settle the messages received in "peekLock" mode.
Once the receiver is created you can use choose between 3 ways to receive messages:
You can read more about how sessions work here.
ServiceBusAdministrationClient
lets you manage a namespace with CRUD operations on the entities(queues, topics, and subscriptions) and on the rules of a subscription.
- Supports authentication with a service bus connection string as well as with the AAD credentials from
@azure/identity
similar to theServiceBusClient
.
Note: Service Bus doesn't support setting CORS rules for namespaces yet, hence ServiceBusAdministrationClient
won't work in the browser without disabling web-security. For more info, refer here.
// Get the connection string from the portal
// OR
// use the token credential overload, provide the host name of your Service Bus instance and the AAD credentials from the @azure/identity library
const serviceBusAdministrationClient = new ServiceBusAdministrationClient("<connectionString>");
// Similarly, you can create topics and subscriptions as well.
const createQueueResponse = await serviceBusAdministrationClient.createQueue(queueName);
console.log("Created queue with name - ", createQueueResponse.name);
const queueRuntimeProperties =
await serviceBusAdministrationClient.getQueueRuntimeProperties(queueName);
console.log("Number of messages in the queue = ", queueRuntimeProperties.totalMessageCount);
await serviceBusAdministrationClient.deleteQueue(queueName);
- Sample for reference - administrationClient.ts
Here's some initial steps to start diagnosing issues. For more information please refer to the Service Bus Troubleshooting Guide.
The Service Bus library depends on the rhea-promise library for managing connections, sending and receiving messages over the AMQP protocol.
You can set the following environment variable to get the debug logs when using this library.
- Getting debug logs from the Service Bus SDK
export DEBUG=azure*
- Getting debug logs from the Service Bus SDK and the protocol level library.
export DEBUG=azure*,rhea*
- If you are not interested in viewing the message transformation (which consumes lot of console/disk space) then you can set the
DEBUG
environment variable as follows:
export DEBUG=azure*,rhea*,-rhea:raw,-rhea:message,-azure:core-amqp:datatransformer
- If you are interested only in errors, then you can set the
DEBUG
environment variable as follows:
export DEBUG=azure:service-bus:error,azure:core-amqp:error,rhea-promise:error,rhea:events,rhea:frames,rhea:io,rhea:flow
- Set the
DEBUG
environment variable as shown above - Run your test script as follows:
- Logging statements from your test script go to
out.log
and logging statements from the sdk go todebug.log
.node your-test-script.js > out.log 2>debug.log
- Logging statements from your test script and the sdk go to the same file
out.log
by redirecting stderr to stdout (&1), and then redirect stdout to a file:node your-test-script.js >out.log 2>&1
- Logging statements from your test script and the sdk go to the same file
out.log
.node your-test-script.js &> out.log
Please take a look at the samples directory for detailed examples on how to use this library to send and receive messages to/from Service Bus Queues, Topics and Subscriptions.
If you'd like to contribute to this library, please read the contributing guide to learn more about how to build and test the code.