NServiceBus endpoints can be hosted in Service Fabric using any of these three options:
- Stateless services
- Stateful services
- Guest executable
Refer to the Service Fabric documentation for more information on when to use each option.
The Actor model is another Service Fabric programming model. It is not currently supported by NServiceBus.
Stateless service
Hosting with a stateless service is similar to self-hosting with Azure App Service). Endpoints are stateless and use storage external to Service Fabric to manage data needed for their operation. Endpoints can be scaled out, leveraging competing consumer at the transport level.
With stateless services, the number of service instances can range from one to the number of nodes in the cluster - 1
. Endpoints are self-hosted and should be started using a custom Service Fabric ICommunicationListener
implementation.
public class StatelessEndpointCommunicationListener :
ICommunicationListener
{
IEndpointInstance endpointInstance;
public async Task<string> OpenAsync(CancellationToken cancellationToken)
{
var endpointName = "Sales";
var endpointConfiguration = new EndpointConfiguration(endpointName);
// endpoint configuration
endpointInstance = await Endpoint.Start(endpointConfiguration);
return endpointName;
}
public Task CloseAsync(CancellationToken cancellationToken)
{
return endpointInstance.Stop();
}
public void Abort()
{
CloseAsync(CancellationToken.None);
}
}
If stateless services are used to host web application frameworks, such as ASP.NET, ASP.NET Core, or WebAPI, it is recommended to start the endpoint inside the service collection extensions instead of the communication listener, as shown in using NServiceBus in an ASP.NET Core WebAPI application. This approach is simpler than having to coordinate multiple communication listeners since no coordination is needed between the listeners. If only stateless services are used to host web application frameworks, it might be useful to consider Azure AppServices. For more guidance, refer to the Azure App Service, Virtual Machines, Service Fabric, and Cloud Services comparison guidance.
Stateful service
The process of configuring and starting an endpoint hosted in a stateful service is very similar to the stateless service hosting approach. The main difference is that the endpoint cannot be started until the OpenAsync
method has returned because the StateManager
instance has not been fully configured yet. This is trivial to solve by calling the Endpoint.
operation from the RunAsync
operation instead.
public class StatefulEndpointCommunicationListener :
ICommunicationListener
{
IReliableStateManager stateManager;
IEndpointInstance endpointInstance;
EndpointConfiguration endpointConfiguration;
public StatefulEndpointCommunicationListener(IReliableStateManager stateManager)
{
this.stateManager = stateManager;
}
public async Task<string> OpenAsync(CancellationToken cancellationToken)
{
var endpointName = "Sales";
endpointConfiguration = new EndpointConfiguration(endpointName);
// configure endpoint with state manager dependency
return endpointName;
}
public async Task RunAsync()
{
endpointInstance = await Endpoint.Start(endpointConfiguration);
}
public Task CloseAsync(CancellationToken cancellationToken)
{
return endpointInstance.Stop();
}
public void Abort()
{
CloseAsync(CancellationToken.None);
}
}
class MyStatefulService :
StatefulService
{
StatefulEndpointCommunicationListener listener;
public MyStatefulService(StatefulServiceContext context)
: base(context)
{ }
protected override IEnumerable<ServiceReplicaListener> CreateServiceReplicaListeners()
{
listener = new StatefulEndpointCommunicationListener(StateManager);
return new List<ServiceReplicaListener>
{
new ServiceReplicaListener(context => listener)
};
}
protected override Task RunAsync(CancellationToken cancellationToken)
{
return listener.RunAsync();
}
}
Due to characteristics of stateful services, i.e. data partitioning and local data storage, additional configuration aspects must be considered:
- The service partitioning schema must be well-defined before the first deployment occurs (repartitioning requires all data to be deleted)
- Messages must be routed among the shards according to the partitioning schema
- A single instance of an NServiceBus endpoint will be running on the primary replica for each partition
See Service Fabric Partition Aware Routing for more information on how to host NServiceBus with stateful services and to learn how to configure routing between service partitions and persist data in reliable collections.
NServiceBus provides persistence based on reliable collections for saga and outbox data. See Service Fabric persistence for details.
Guest executable
The guest executable option allows packaging and deployment of an existing endpoint into Service Fabric with minimal or no change at all. Service Fabric treats a guest executable as a stateless service.
This option can be used as an interim solution for the endpoints that eventually need to be converted to Service Fabric services but cannot be converted right away.
While executables can be packaged and deployed to Service Fabric without much effort, the Service Fabric hosting environment might not support all local dependencies. For example, endpoints running on the MSMQ transport should be migrated to another transport. The reason for this is that Service Fabric reallocates processes to different machines based on metrics such as CPU load, but these local dependencies will not move along with it.
Hosting NServiceBus in a standalone cluster
Service Fabric can be deployed to run in any environment that contains a set of interconnected Windows Server machines. See the official documentation for details.
On Azure, Service Fabric can be hosted with Azure Service Fabric service.