Default Bus Configuration
Overview
This document explains the NServiceBus configuration system in FlexBase applications, using the EBusiness sample as a reference. The bus configuration provides a flexible, environment-aware messaging system that supports multiple transport and persistence options.
Architecture Overview
The NServiceBus configuration in FlexBase follows a strategy pattern where different configurations are selected based on the environment and requirements. This allows for seamless transitions between development, staging, and production environments.
Configuration Flow
Environment Detection β Configuration Selection β Transport Setup β Persistence Setup β Routing Configuration
Project Structure
EBusiness.Nsb Project
The EBusiness.Nsb
project contains all NServiceBus configuration implementations:
EBusiness.Nsb/
βββ EBusiness.Nsb.csproj # Project file with NServiceBus packages
βββ LearningNsbConfiguration.cs # Development/Testing transport
βββ RabbitMqNsbConfiguration.cs # Production RabbitMQ transport
βββ SqlNsbConfiguration.cs # SQL Server transport
βββ AzureServiceNsbConfiguration.cs # Azure Service Bus transport
βββ AzureStorageQueueNsbConfiguration.cs # Azure Storage Queue transport
βββ AmazonSQSNsbConfiguration.cs # Amazon SQS transport
βββ MyCustomNsbConfiguration.cs # Template for custom configurations
Dependencies
The project references multiple FlexBase NServiceBus packages:
<PackageReference Include="Sumeru.Flex.ServiceBus.Nsb" Version="9.2.0" />
<PackageReference Include="Sumeru.Flex.ServiceBus.Nsb.Azure.Storage" Version="9.2.0" />
<PackageReference Include="Sumeru.Flex.ServiceBus.Nsb.Learning" Version="9.2.0" />
<PackageReference Include="Sumeru.Flex.ServiceBus.Nsb.OnPremises.Rabbit" Version="9.2.0" />
<PackageReference Include="Sumeru.Flex.ServiceBus.Nsb.Amazon.SQS" Version="9.2.0" />
<PackageReference Include="Sumeru.Flex.ServiceBus.Nsb.Azure.ServiceBus" Version="9.2.0" />
<PackageReference Include="Sumeru.Flex.ServiceBus.Nsb.SqlTransport" Version="9.2.0" />
<PackageReference Include="Sumeru.Flex.ServiceBus.Nsb.SqlPersistence" Version="9.2.0" />
Configuration Selection Logic
BusEndPointConfig.cs - Environment-Based Selection
The BusEndPointConfig.cs
file contains the logic for selecting the appropriate NServiceBus configuration based on the environment:
public static EndpointConfiguration GetEndpoint(IConfiguration configuration, IHostEnvironment env, List<BusRouteConfig> routes)
{
string endPointName = configuration.GetSection("EndPoint")["Name"];
NsbDefaultEndpointConfiguration endPointConfig;
if (env.IsDevelopment())
{
endPointConfig = new LearningNsbConfiguration(endPointName, routes, configuration, env);
}
else if (env.IsStaging())
{
endPointConfig = new RabbitMqNsbConfiguration(endPointName, routes, configuration, env);
}
else if (env.IsProduction())
{
endPointConfig = new RabbitMqNsbConfiguration(endPointName, routes, configuration, env);
}
else
{
endPointConfig = new RabbitMqNsbConfiguration(endPointName, routes, configuration, env);
}
return endPointConfig;
}
Environment Mapping
Development
LearningNsbConfiguration
Learning Transport
Learning Persistence
Local development, testing
Staging
RabbitMqNsbConfiguration
RabbitMQ
SQL Server
Pre-production testing
Production
RabbitMqNsbConfiguration
RabbitMQ
SQL Server
Live production environment
Default
RabbitMqNsbConfiguration
RabbitMQ
SQL Server
Fallback configuration
Transport Configurations
1. Learning Transport (Development)
File: LearningNsbConfiguration.cs
public class LearningNsbConfiguration : NsbBaseConfiguration
{
public LearningNsbConfiguration(string endpointName, IEnumerable<BusRouteConfig> routes, IConfiguration configuration, IHostEnvironment env, string errorQueueName = "error")
: base(endpointName, configuration, env, errorQueueName)
{
// Configure persistence
var persistence = this.UsePersistence<LearningPersistence>();
// Configure transport
var transport = this.UseTransport<LearningTransport>();
// Configure routing
var routing = transport.Routing();
foreach (var route in routes)
{
routing.RouteToEndpoint(route.Assembly, route.Destination);
}
}
}
Characteristics:
File-Based: Stores messages in local file system
No Dependencies: No external infrastructure required
Development Only: Not suitable for production
Auto-Cleanup: Automatically manages message storage
Configuration Requirements:
No connection strings required
Creates
.learningtransport
directory automaticallyPerfect for local development and testing
2. RabbitMQ Transport (Production)
File: RabbitMqNsbConfiguration.cs
public class RabbitMqNsbConfiguration : NsbBaseConfiguration
{
public RabbitMqNsbConfiguration(string endpointName, IEnumerable<BusRouteConfig> routes, IConfiguration configuration, IHostEnvironment env, string errorQueueName = "error")
: base(endPointName, configuration, env, errorQueueName)
{
string sqlPersistenceConnectionString = configuration.GetSection("FlexBase")["SqlPersistenceConnectionString"];
string rabbitMqConnectionString = configuration.GetSection("FlexBase")["RabbitMqConnectionString"];
// Configure persistence
var persistence = this.UsePersistence<SqlPersistence>();
persistence.SqlDialect<SqlDialect.MsSqlServer>();
persistence.ConnectionBuilder(() => new SqlConnection(sqlPersistenceConnectionString));
// Configure transport
var transport = this.UseTransport<RabbitMQTransport>();
transport.ConnectionString(rabbitMqConnectionString);
transport.UseConventionalRoutingTopology(QueueType.Classic);
// Configure routing
var routing = transport.Routing();
foreach (var route in routes)
{
routing.RouteToEndpoint(route.Assembly, route.Destination);
}
}
}
Characteristics:
High Performance: Excellent for high-throughput scenarios
Reliable: Message durability and delivery guarantees
Scalable: Horizontal scaling capabilities
Production Ready: Suitable for enterprise environments
Configuration Requirements:
{
"FlexBase": {
"SqlPersistenceConnectionString": "Data Source=YourServer;Initial Catalog=YourPersistenceDb;...",
"RabbitMqConnectionString": "amqp://YourUser:YourPassword@YourRabbitMqHost:YourPort"
}
}
3. SQL Server Transport
File: SqlNsbConfiguration.cs
public class SqlNsbConfiguration : NsbBaseConfiguration
{
public SqlNsbConfiguration(string endpointName, IEnumerable<BusRouteConfig> routes, IConfiguration configuration, IHostEnvironment env, string errorQueueName = "error")
: base(endPointName, configuration, env, errorQueueName)
{
string sqlPersistenceConnectionString = configuration.GetSection("FlexBase")["SqlPersistenceConnectionString"];
string sqlTransportConnectionString = configuration.GetSection("FlexBase")["SqlTransportConnectionString"];
// Configure persistence
var persistence = this.UsePersistence<SqlPersistence>();
persistence.SqlDialect<SqlDialect.MsSqlServer>();
persistence.ConnectionBuilder(() => new SqlConnection(sqlPersistenceConnectionString));
// Configure transport
var transport = new SqlServerTransport(sqlTransportConnectionString);
this.UseTransport(transport);
// Configure routing
var routing = this.UseTransport(transport);
foreach (var route in routes)
{
routing.RouteToEndpoint(route.Assembly, route.Destination);
}
}
}
Characteristics:
Database-Based: Uses SQL Server for message transport
Transactional: Leverages SQL Server transactions
Familiar: Easy to monitor and debug
Reliable: ACID compliance for message delivery
Configuration Requirements:
{
"FlexBase": {
"SqlPersistenceConnectionString": "Data Source=YourServer;Initial Catalog=YourPersistenceDb;...",
"SqlTransportConnectionString": "Data Source=YourServer;Initial Catalog=YourTransportDb;..."
}
}
4. Azure Service Bus Transport
File: AzureServiceNsbConfiguration.cs
public class AzureServiceNsbConfiguration : NsbBaseConfiguration
{
public AzureServiceNsbConfiguration(string endpointName, IEnumerable<BusRouteConfig> routes, IConfiguration configuration, IHostEnvironment env, string errorQueueName = "error")
: base(endPointName, configuration, env, errorQueueName)
{
string sqlPersistenceConnectionString = configuration.GetSection("FlexBase")["SqlPersistenceConnectionString"];
string azureServiceBusConnectionString = configuration.GetSection("FlexBase")["AzureServiceBusConnectionString"];
// Configure persistence
var persistence = this.UsePersistence<SqlPersistence>();
persistence.SqlDialect<SqlDialect.MsSqlServer>();
persistence.ConnectionBuilder(() => new SqlConnection(sqlPersistenceConnectionString));
// Configure transport
var transport = new AzureServiceBusTransport(azureServiceBusConnectionString);
this.UseTransport(transport);
// Configure routing
var routing = this.UseTransport(transport);
foreach (var route in routes)
{
routing.RouteToEndpoint(route.Assembly, route.Destination);
}
}
}
Characteristics:
Cloud-Native: Fully managed Azure service
Scalable: Auto-scaling capabilities
Reliable: 99.9% SLA guarantee
Integrated: Works seamlessly with other Azure services
Configuration Requirements:
{
"FlexBase": {
"SqlPersistenceConnectionString": "Data Source=YourServer;Initial Catalog=YourPersistenceDb;...",
"AzureServiceBusConnectionString": "Endpoint=sb://YourNamespace.servicebus.windows.net/;SharedAccessKeyName=YourKeyName;SharedAccessKey=YourKey"
}
}
5. Azure Storage Queue Transport
File: AzureStorageQueueNsbConfiguration.cs
public class AzureStorageQueueNsbConfiguration : NsbBaseConfiguration
{
public AzureStorageQueueNsbConfiguration(string endpointName, IEnumerable<BusRouteConfig> routes, IConfiguration configuration, IHostEnvironment env, string errorQueueName = "error")
: base(endPointName, configuration, env, errorQueueName)
{
string azureConnectionString = configuration.GetSection("FlexBase")["AzureStorageConnectionString"];
// Configure persistence
var persistence = this.UsePersistence<AzureTablePersistence>();
persistence.ConnectionString(azureConnectionString);
// Configure transport
var queueServiceClient = new QueueServiceClient(azureConnectionString, new QueueClientOptions());
var blobServiceClient = new BlobServiceClient(azureConnectionString, new BlobClientOptions());
var tableServiceClient = new TableServiceClient(azureConnectionString, new TableClientOptions());
var transport = new AzureStorageQueueTransport(queueServiceClient, blobServiceClient, tableServiceClient)
{
ReceiverBatchSize = 20,
MaximumWaitTimeWhenIdle = TimeSpan.FromSeconds(1),
DegreeOfReceiveParallelism = 16,
PeekInterval = TimeSpan.FromMilliseconds(100),
MessageInvisibleTime = TimeSpan.FromSeconds(30)
};
// Configure routing
var routing = this.UseTransport(transport);
foreach (var route in routes)
{
routing.RouteToEndpoint(route.Assembly, route.Destination);
routing.RegisterPublisher(route.Assembly, route.Destination);
}
}
}
Characteristics:
Cost-Effective: Lower cost than Service Bus
Simple: Easy to set up and manage
Scalable: Handles high message volumes
Azure-Native: Integrated with Azure ecosystem
Configuration Requirements:
{
"FlexBase": {
"AzureStorageConnectionString": "DefaultEndpointsProtocol=https;AccountName=YourAccount;AccountKey=YourKey;EndpointSuffix=core.windows.net"
}
}
6. Amazon SQS Transport
File: AmazonSQSNsbConfiguration.cs
public class AmazonSQSNsbConfiguration : NsbBaseConfiguration
{
public AmazonSQSNsbConfiguration(string endpointName, IEnumerable<BusRouteConfig> routes, IConfiguration configuration, IHostEnvironment env, string errorQueueName = "error")
: base(endPointName, configuration, env, errorQueueName)
{
string sqlPersistenceConnectionString = configuration.GetSection("FlexBase")["SqlPersistenceConnectionString"];
string s3BucketName = configuration.GetSection("FlexBase")["AmazonSQSTransportBucketName"];
string s3KeyPrefix = configuration.GetSection("FlexBase")["AmazonSQSTransportKeyPrefix"];
// Configure persistence
var persistence = this.UsePersistence<SqlPersistence>();
persistence.SqlDialect<SqlDialect.MsSqlServer>();
persistence.ConnectionBuilder(() => new SqlConnection(sqlPersistenceConnectionString));
// Configure transport
var transport = new SqsTransport
{
S3 = new S3Settings(
bucketForLargeMessages: s3BucketName,
keyPrefix: s3KeyPrefix,
s3Client: new AmazonS3Client())
};
// Configure routing
var routing = this.UseTransport(transport);
foreach (var route in routes)
{
routing.RouteToEndpoint(route.Assembly, route.Destination);
}
}
}
Characteristics:
AWS-Native: Fully integrated with AWS services
Scalable: Auto-scaling message queues
Reliable: High availability and durability
Cost-Effective: Pay-per-use pricing model
Configuration Requirements:
{
"FlexBase": {
"SqlPersistenceConnectionString": "Data Source=YourServer;Initial Catalog=YourPersistenceDb;...",
"AmazonSQSTransportBucketName": "YourS3BucketName",
"AmazonSQSTransportKeyPrefix": "YourKeyPrefix"
}
}
Service Registration
BusEndPointConfig.cs - Service Registration
The BusEndPointConfig.cs
file also handles service registration for dependency injection:
public static void AddFlexBaseBusServices(this IServiceCollection services)
{
services.AddSingleton<IFlexServiceBusBridge, NsbServiceBusBridge>();
services.AddTransient<FlexBusSendOptions, NsbSendOptions>();
}
What This Does:
Service Bus Bridge: Registers the NServiceBus bridge as a singleton
Send Options: Registers send options for message publishing
Dependency Injection: Makes bus services available throughout the application
Configuration Best Practices
1. Environment-Specific Configuration
// Development
if (env.IsDevelopment())
{
endPointConfig = new LearningNsbConfiguration(endPointName, routes, configuration, env);
}
// Staging
else if (env.IsStaging())
{
endPointConfig = new RabbitMqNsbConfiguration(endPointName, routes, configuration, env);
}
// Production
else if (env.IsProduction())
{
endPointConfig = new RabbitMqNsbConfiguration(endPointName, routes, configuration, env);
}
2. Connection String Management
{
"FlexBase": {
"SqlPersistenceConnectionString": "Data Source=YourServer;Initial Catalog=YourPersistenceDb;...",
"RabbitMqConnectionString": "amqp://YourUser:YourPassword@YourRabbitMqHost:YourPort",
"AzureServiceBusConnectionString": "Endpoint=sb://YourNamespace.servicebus.windows.net/;...",
"AzureStorageConnectionString": "DefaultEndpointsProtocol=https;AccountName=YourAccount;...",
"AmazonSQSTransportBucketName": "YourS3BucketName",
"AmazonSQSTransportKeyPrefix": "YourKeyPrefix"
}
}
3. Error Handling
Guard.AgainstNullAndEmpty("SqlPersistenceConnectionString for connection string cannot be empty",
configuration.GetSection("FlexBase")["SqlPersistenceConnectionString"]);
4. Routing Configuration
var routing = transport.Routing();
foreach (var route in routes)
{
routing.RouteToEndpoint(route.Assembly, route.Destination);
}
Custom Configuration Template
MyCustomNsbConfiguration.cs
public class MyCustomNsbConfiguration : EndpointConfiguration
{
public MyCustomNsbConfiguration(string endpointName, string errorQueueName = "error") : base(endpointName)
{
this.SendFailedMessagesTo(errorQueueName);
// Add all other NSB Configuration here
// - Transport configuration
// - Persistence configuration
// - Routing configuration
// - Serialization settings
// - Error handling
// - Performance tuning
}
}
Use Cases:
Custom Requirements: Specific business needs not covered by standard configurations
Performance Tuning: Optimized settings for specific scenarios
Integration: Custom transport or persistence providers
Testing: Specialized configurations for testing scenarios
Performance Considerations
Transport Selection Guidelines
Development
Learning Transport
No external dependencies, easy setup
Small Scale
SQL Server Transport
Familiar, easy to monitor
High Throughput
RabbitMQ Transport
Excellent performance, reliable
Cloud-Native
Azure Service Bus
Fully managed, integrated
Cost-Sensitive
Azure Storage Queue
Lower cost, good performance
AWS Environment
Amazon SQS
Native AWS integration
Persistence Selection Guidelines
Development
Learning Persistence
No external dependencies
Production
SQL Server Persistence
Reliable, familiar, ACID compliance
Azure
Azure Table Persistence
Native Azure integration
Troubleshooting
Common Issues
Connection String Errors
Verify connection strings in configuration
Check network connectivity
Validate credentials
Transport Failures
Ensure transport service is running
Check firewall settings
Verify endpoint configuration
Routing Issues
Verify route configuration
Check assembly references
Validate destination endpoints
Performance Problems
Monitor message throughput
Check resource utilization
Consider transport scaling
Debugging Tips
Enable Logging: Use structured logging to track message flow
Monitor Queues: Check queue depths and processing rates
Health Checks: Implement health checks for transport and persistence
Metrics: Use application insights or similar tools for monitoring
Key Benefits
Environment Awareness: Automatic configuration based on environment
Multiple Transports: Support for various messaging technologies
Flexible Persistence: Multiple persistence options
Easy Configuration: Simple configuration management
Production Ready: Battle-tested configurations
Scalable: Supports high-throughput scenarios
Reliable: Built-in error handling and retry mechanisms
Maintainable: Clear separation of concerns
Testable: Easy to test with different configurations
This NServiceBus configuration system provides a robust, scalable, and maintainable messaging infrastructure that adapts to different environments and requirements! π
Last updated