Aspire is a stack for developing distributed applications provided by Microsoft.
This sample shows an Aspire AppHost project that orchestrates multiple NServiceBus endpoints, wiring up the required infrastructure pieces including a RabbitMQ broker and PostgreSQL database.
If you're missing certain capabilities to use Aspire with NServiceBus, share them and help shape the future of the platform.
Running the sample
- Run the AspireDemo.AppHost project
- Open the Aspire dashboard
- Review the metrics, traces, and structured log entries of each of the resources
This sample requires Docker to run. Ensure the predefined container ports are free and available.
Code walkthrough
AspireDemo.AppHost
The Aspire orchestration project defines multiple resources and the relationships between them:
- A RabbitMQ instance named
transport - A PostgreSQL server named
database- A database named
shipping-db - An instance of pgweb to access the database
- A database named
- Four projects, each of which is an NServiceBus endpoint. All of these projects reference the
transportresource.clientuibillingsalesshipping- also has a reference to theshipping-dbresource
- ServiceControl error, audit and monitoring instances
- ServicePulse
using Particular.Aspire.Hosting.ServicePlatform.Transport;
var builder = DistributedApplication.CreateBuilder(args);
var transportUserName = builder.AddParameter("transportUserName", "guest", secret: true);
var transportPassword = builder.AddParameter("transportPassword", "guest", secret: true);
var transport = builder.AddRabbitMQ("transport", transportUserName, transportPassword)
.WithManagementPlugin(15672)
.WithUrlForEndpoint("management", url => url.DisplayText = "RabbitMQ Management");
transportUserName.WithParentRelationship(transport);
transportPassword.WithParentRelationship(transport);
var database = builder.AddPostgres("database");
database.WithPgAdmin(resource =>
{
resource.WithParentRelationship(database);
resource.WithUrlForEndpoint("http", url => url.DisplayText = "pgAdmin");
});
var shippingDB = database.AddDatabase("shipping-db");
var platform = builder
.AddParticularPlatform("particular")
.WithTransportRabbitMQ(RabbitMqRouting.QuorumConventionalRouting, transport)
.AddDefaultComponents();
builder.AddProject<Projects.Billing>("Billing")
.WithParticularPlatform(platform);
var sales = builder.AddProject<Projects.Sales>("Sales")
.WithParticularPlatform(platform);
builder.AddProject<Projects.ClientUI>("ClientUI")
.WaitFor(sales)
.WithParticularPlatform(platform);
builder.AddProject<Projects.Shipping>("Shipping")
.WithReference(shippingDB)
.WaitFor(shippingDB)
.WithParticularPlatform(platform)
.WaitFor(platform);
builder.Build().Run();
AspireDemo.ServiceDefaults
The Aspire service defaults project provides extension methods to configure application hosts in a standardized way. This project is referenced by all of the NServiceBus endpoint projects.
The OpenTelemetry configuration has been updated to include NServiceBus metrics and traces.
builder.Services.AddOpenTelemetry()
.WithMetrics(metrics =>
{
metrics.AddMeter("NServiceBus.*")
.AddAspNetCoreInstrumentation()
.AddHttpClientInstrumentation()
.AddRuntimeInstrumentation();
})
.WithTracing(tracing =>
{
tracing.AddSource(builder.Environment.ApplicationName)
.AddSource("NServiceBus.*")
.AddAspNetCoreInstrumentation(tracing =>
// Exclude health check requests from tracing
tracing.Filter = context =>
!context.Request.Path.StartsWithSegments(HealthEndpointPath)
&& !context.Request.Path.StartsWithSegments(AlivenessEndpointPath)
)
// Uncomment the following line to enable gRPC instrumentation
// (requires the OpenTelemetry.Instrumentation.GrpcNetClient package)
//.AddGrpcClientInstrumentation()
.AddHttpClientInstrumentation();
});
Endpoint projects
Each of the endpoint projects contain the same code to create an application host, apply the configuration from the ServiceDefaults project on the NServiceBus endpoint.
var builder = Host.CreateApplicationBuilder();
builder
.AddServiceDefaults()
.AddNServiceBusEndpoint("Sales");
await builder.Build().RunAsync();
The service defaults extension method retrieves the connection string for the RabbitMQ broker and configures NServiceBus to use it as a transport:
var connectionString = builder.Configuration.GetConnectionString("transport");
if (connectionString is null)
{
throw new InvalidOperationException
($"No transport configured. Provide a 'ConnectionStrings:transport'.");
}
var routing = endpointConfiguration.UseTransport
(new RabbitMQTransport(RoutingTopology.Conventional(QueueType.Quorum), connectionString));
The Shipping endpoint additionally retrieves the connection string for the PostgreSQL database and configures NServiceBus to use it as a ServiceControl database:
var persistenceConnection = builder.Configuration.GetConnectionString("shipping-db");
var persistence = endpointConfiguration.UsePersistence<SqlPersistence>();
persistence.ConnectionBuilder(
connectionBuilder: () => new NpgsqlConnection(persistenceConnection));
Additionally, the shared config enables NServiceBus installers. Every time the application host is run, the transport and ServiceControl database are recreated and will not contain the queues and tables needed for the endpoints to run. Enabling installers allows NServiceBus to set up the assets that it needs at runtime.
endpointConfiguration.EnableInstallers();
If you're missing certain capabilities to use Aspire with NServiceBus, share them and help shape the future of the platform.