For years, developers working with Azure Service Bus have longed for a local emulator to streamline development and testing. Relying on cloud-based instances for every iteration was costly, time-consuming, and often impractical. But as of November 19, 2024, Microsoft has answered those prayers with the official release of the Azure Service Bus Local Emulator!
Azure Service Bus Emulator is not a full replacement for Azure Service bus but is aimed at local development and testing never the less lets look into how to the features it offers and how to use it.
Getting Started with the emulator
Using the Service Bus emulator is simple:
- Create a Config file.
- Run the docker Compose file
- Connect.
Config File
The Config.json is the only way to configure the Service bus emulator, I have created a nuget package and supporting documentation to allow for programmatic creation of the file as follows:
Install the configuration builder package
dotnet add package ReardonTech.AzureServiceBusEmulator.Configuration
Then run the following example
var asbEmulatorConfig = AsbEmulatorConfigurationBuilder.WithNamespace("local", nOptions =>
nOptions.WithQueue("Queue1")
.WithQueue("Queue2")
.WithTopic("Topic1", tOptions =>
tOptions.WithSubscription("Subscription1")
.WithSubscription("Subscription2"))
).Build();
File.WriteAllText("Config.json", JsonSerializer.Serialize(asbEmulatorConfig));
Config.json
{
"UserConfig" : {
"Namespaces" : [ {
"Name" : "local",
"Queues" : [ {
"Name" : "Queue1",
"Properties" : {
"DeadLetteringOnMessageExpiration" : false,
"DefaultMessageTimeToLive" : "PT1H",
"DuplicateDetectionHistoryTimeWindow" : "PT20S",
"ForwardDeadLetteredMessagesTo" : "",
"ForwardTo" : "",
"LockDuration" : "PT1M",
"MaxDeliveryCount" : 3,
"RequiresDuplicateDetection" : false,
"RequiresSession" : false
}
}, {
"Name" : "Queue2",
"Properties" : {
"DeadLetteringOnMessageExpiration" : false,
"DefaultMessageTimeToLive" : "PT1H",
"DuplicateDetectionHistoryTimeWindow" : "PT20S",
"ForwardDeadLetteredMessagesTo" : "",
"ForwardTo" : "",
"LockDuration" : "PT1M",
"MaxDeliveryCount" : 3,
"RequiresDuplicateDetection" : false,
"RequiresSession" : false
}
} ],
"Topics" : [ {
"Name" : "Topic1",
"Properties" : {
"DefaultMessageTimeToLive" : "PT1H",
"DuplicateDetectionHistoryTimeWindow" : "PT20S",
"RequiresDuplicateDetection" : false
},
"Subscriptions" : [ {
"Name" : "Subscription1",
"Properties" : {
"DeadLetteringOnMessageExpiration" : false,
"DefaultMessageTimeToLive" : "PT1H",
"DuplicateDetectionHistoryTimeWindow" : "PT20S",
"ForwardDeadLetteredMessagesTo" : "",
"ForwardTo" : "",
"LockDuration" : "PT1M",
"MaxDeliveryCount" : 3,
"RequiresDuplicateDetection" : false,
"RequiresSession" : false
},
"Rules" : [ ]
}, {
"Name" : "Subscription2",
"Properties" : {
"DeadLetteringOnMessageExpiration" : false,
"DefaultMessageTimeToLive" : "PT1H",
"DuplicateDetectionHistoryTimeWindow" : "PT20S",
"ForwardDeadLetteredMessagesTo" : "",
"ForwardTo" : "",
"LockDuration" : "PT1M",
"MaxDeliveryCount" : 3,
"RequiresDuplicateDetection" : false,
"RequiresSession" : false
},
"Rules" : [ ]
} ]
} ]
} ],
"Logging" : {
"Type" : "File"
}
}
}
Docker Compose
The easiest way to run the docker compose, once you have the configuration file above is to create a .env
file and then run docker compose.
docker-compose -f .\Docker-Compose.yml up -d
.env
# Environment file for user defined variables in docker-compose.yml
# 1. CONFIG_PATH: Path to Config.json file
CONFIG_PATH="./Config.json"
# 2. ACCEPT_EULA: Pass 'Y' to accept license terms for Azure SQL Edge and Azure Service Bus emulator.
ACCEPT_EULA="Y"
# 3. MSSQL_SA_PASSWORD to be filled by user as per policy : https://learn.microsoft.com/en-us/sql/relational-databases/security/strong-passwords?view=sql-server-linux-ver16
SQL_PASSWORD: "Password123!"
CONFIG_PATH
to he location of the Generated Config.json file. As we wont be exposing the sql Server outside of the docker network it is less important.Docker Compose File
name: microsoft-azure-servicebus-emulator
services:
emulator:
container_name: "servicebus-emulator"
image: mcr.microsoft.com/azure-messaging/servicebus-emulator:latest
volumes:
- "${CONFIG_PATH}:/ServiceBus_Emulator/ConfigFiles/Config.json"
ports:
- "5672:5672"
environment:
SQL_SERVER: sqledge
MSSQL_SA_PASSWORD: "${SQL_PASSWORD}" # Password should be same as what is set for SQL Edge
ACCEPT_EULA: ${ACCEPT_EULA}
depends_on:
- sqledge
networks:
sb-emulator:
aliases:
- "sb-emulator"
sqledge:
container_name: "sqledge"
image: "mcr.microsoft.com/azure-sql-edge:latest"
networks:
sb-emulator:
aliases:
- "sqledge"
environment:
ACCEPT_EULA: ${ACCEPT_EULA}
MSSQL_SA_PASSWORD: "${SQL_PASSWORD}" # To be filled by user as per policy : https://learn.microsoft.com/en-us/sql/relational-databases/security/strong-passwords?view=sql-server-linux-ver16
networks:
sb-emulator:
Connection your Application
To connect your existing application up to the Service Bus Emulator update your connection string to the following:
Endpoint=sb://localhost;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=SAS_KEY_VALUE;UseDevelopmentEmulator=true;
You do not have to change the SharedAccessKeyName
or SharedAccessKey
as they are ignored by the Emulator.
If you are mapping to a different port you change the address localhost:5677
(for port 5677)
var client =
new ServiceBusClient(
"Endpoint=sb://localhost;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=SAS_KEY_VALUE;UseDevelopmentEmulator=true;");
For working example please checkout my sample project here
Whats supported and features
- Core Functionality : while not everything is supported, most core functionality is supported.
- Queues and Topics
- Subscriptions and Filters
- Message sessions
- Dead Letter queues
- AMQP protocol : Ensure realistic behavior.
- Dockerised for easy deployment and management : Works the same cross system without needing to install dependencies, also allows for easy clean up.
- Actively maintained by Microsoft : Will be kept upt to date.
Key Features not supported
- Management Interface : In most projects I have used over the years there has been some automated managed checks, usually to check if a Subscription or Topic exists and create it if it does not. These must be enabled when using Azure Service Bus Emulator as it does not support them and the Service Bus Admin client will throw an error as the emulator is not listening on port 443.
- Large Message Handling : Messages above 256kb are not supported, Queues or Topics may not exceed 100mb.
- Maximum messaging entities : there is a maximum of 50 Queues or Topics allowable in any one Namespace, as well as a Maximum of 50 Subscriptions in a Topic.
- UI Portal : There is not UI portal or visual metrics, all configuration must be done via the Config file.
- Partitioned Entities : Partitioned Entities are not supported.
- Azure Specific Integration : AzureAD, vNet Integration, Activity Logs, and the likes are not supported.
- Auto scaling : Resources will not scale, and Geo-Disaster recovery is also not supported.
Conclusion
The release of the Azure Service Bus Local Emulator marks a significant step forward in simplifying and accelerating development with Azure Service Bus. By providing a robust and accessible local development environment, Microsoft has empowered developers to build and test messaging solutions with greater speed, efficiency, and cost-effectiveness.
Whether you’re a seasoned Azure developer or just starting your journey with Service Bus, the emulator is an invaluable tool to add to your arsenal. Dive in, explore its capabilities, and experience the benefits of local development firsthand. And don’t forget to contribute your feedback to the project’s GitHub repository to help shape its future development!