NServiceBus Host

Project Hosting | Nuget: NServiceBus.Host (Version: 4.x)
Target NServiceBus Version: 4.x
Standard support for version 4.x of NServiceBus has expired. For more information see our Support Policy.

The NServiceBus Host takes an opinionated approach to hosting. Endpoints using NServiceBus Host can run as windows services or console application (e.g. during development).

To use the host, create a new C# class library and reference the NServiceBus.Host NuGet package. The package will automatically create a sample endpoint configuration and will set the NServiceBus.Host.exe as the endpoint's startup project.

Application Domains

The NServiceBus.Host.exe creates a separate service Application Domain to run NServiceBus and the user code. The new domain is assigned a configuration file named after the dll that contains the class implementing IConfigureThisEndpoint. All the configuration should be done in that file (as opposed to NServiceBus.Host.exe.config). In most cases that means just adding the app.config file to the project and letting MSBuild take care of renaming it while moving to the bin directory.

When the endpoint configuration is not specified explicitly, the host scans all the assemblies to find it and it does so in the context of the host application domain, not the new service domain. Because of that, when redirecting assembly versions, the assemblyBinding element needs to be present in both NServiceBus.Host.exe.config and app.config.

Endpoint configuration

Assembly scanning

By default, the assembly scanning process of the NServiceBus Host is the same as for a regular endpoint. At startup the host scans the runtime directory to find assemblies that contain configuration for the given endpoint, i.e. classes implementing the IConfigureThisEndpoint interface.

The scanning process can be avoided if the class containing endpoint's configuration is explicitly specified:

Edit
<configuration>
  <appSettings>
    <add key="EndpointConfigurationType"
         value="YourNamespace.YourTypeName, YourAssembly"/>
  </appSettings>
</configuration>

Alternatively, it's possible to control which assemblies should be scanned. That can be done in code by implementing IConfigureThisEndpoint interface:

Edit
public class EndpointConfig :
    IConfigureThisEndpoint,
    IWantCustomInitialization
{
    public void Init()
    {
        // use 'Configure' to configure scanning
    }
}

or during installation by passing values to /scannedAssemblies: parameters.

Initialization

To change core settings such as assembly scanning, container, and serialization format, implement IWantCustomInitialization on the endpoint configuration class (the same class that implements IConfigureThisEndpoint). Start the configuration expression with

Configure.With()
Do not perform any startup behaviors in the Init method.

After the custom initialization is done the regular core INeedInitalization implementations found will be called in the same way as when self hosting.

Startup Behavior

For Versions 7 and above, a new interface called IWantToRunWhenEndpointStartsAndStops has been added. This interface allows code to be executed at startup and shutdown of the Host. For Versions 6 and below, use the Endpoint Instance Start and Stop functionality`.

At startup, the Host invokes all the classes that implement the IWantToRunWhenEndpointStartsAndStopsinterface.

Implementations of IWantToRunWhenEndpointStartsAndStops are not started and stopped on a dedicated thread. They are executed on the thread starting and disposing the endpoint. It is the responsibility of the implementing class to execute its operations in parallel if needed (i.e. for CPU bound work). Failure to do so will prevent the endpoint from being started and/or disposed.
  • Instances of IWantToRunWhenEndpointStartsAndStops are located by assembly scanning and automatically registered into the configured container during endpoint creation. These are registered as Instance Per Call.
  • They are started before the transport and any satellites have started. Therefore the endpoint will not receive any messages until this process has completed.
  • These instances are created by the Container which means they:
  • Will have dependencies injected.
  • Do not require a default constructor.
  • These instances will be started asynchronously in the same method which started the bus.
  • Once created Start is called on each instance asynchronously without awaiting its completion.
  • Instances of IWantToRunWhenEndpointStartsAndStops which successfully start are kept internally to be stopped when the endpoint is stopped.
  • When the endpoint is shut down, the Stop method for each instance of IWantToRunWhenEndpointStartsAndStops is called asynchronously.
  • The instances will be stopped only after the transport and any satellites have stopped. While all instances of IWantToRunWhenEndpointStartsAndStops are being stopped, the endpoint will not handle any messages received.
  • The instances will be stopped asynchronously within the same method which disposed the endpoint.
The endpoint will not start processing messages until all instances of IWantToRunWhenEndpointStartsAndStops.Start are completed.
The Start and Stop methods will block start up and shut down of the endpoint. For any long running methods, use Task.Run so as not to block execution.
In NServiceBus Versions 6 and above, and all integrations that target those versions, all extension points that return Task cannot return a null Task. These APIs must return an instance of a Task. For example either a pending Task, a CompletedTask, or be marked async. For extension points that return a Task<T> return the value directly (for async methods) or wrap the value in a Task.FromResult(value).

Exceptions

Exceptions thrown in the constructors of instances of IWantToRunWhenEndpointStartsAndStops are unhandled by NServiceBus. These will prevent the endpoint from starting up.

Exceptions raised from the Start method will prevent the endpoint from starting. As they are called asynchronously and awaited with Task.WhenAll, an exception may prevent other Start methods from being called.

Exceptions raised from the Stop method will not prevent the endpoint from shutting down. The exceptions will be logged at the Fatal level.

Roles - Built-in configurations

While NServiceBus allows picking and choosing which technologies to use and how to configure each of them, the host packages these choices into three built-in options: AsA_Client, AsA_Server, and AsA_Publisher. All these options make use of XmlSerializer, MsmqTransport, and UnicastBus. The difference is in the configuration:

  • AsA_Client sets MsmqTransport as non-transactional and purges its queue of messages on startup. This means that it starts afresh every time, not remembering anything before a crash. Also, it processes messages using its own permissions, not those of the message sender.
  • AsA_Server sets MsmqTransport as transactional and does not purge messages from its queue on startup. This makes it fault-tolerant.
  • AsA_Publisher extends AsA_Server and indicates to the infrastructure to set up storage for subscription requests, described in the profiles page.

Endpoint Name

Via namespace convention

When using NServiceBus.Host, the namespace of the class implementing IConfigureThisEndpoint will be used as the endpoint name as the default convention. In the following example the endpoint name when running NServiceBus.Host.exe becomes MyServer. This is the recommended way to name a endpoint. Also this emphasizes convention over configuration approach.

Edit
namespace MyServer
{
    using NServiceBus;

    public class EndpointConfigByNamespace :
        IConfigureThisEndpoint,
        AsA_Server
    {
        // ... custom config

Via EndpointName attribute

Set the endpoint name using the [EndpointName] attribute on the endpoint configuration.

This will only work when using NServiceBus host.
Edit
[EndpointName("MyEndpointName")]
public class EndpointConfigWithAttribute :
    IConfigureThisEndpoint,
    AsA_Server
{
    // ... custom config

Default Critical error action

The default Critical Error Action for the Host is:

Edit
if (Environment.UserInteractive)
{
    // so that user can see on their screen the problem
    Thread.Sleep(10000);
}

var fatalMessage = $"NServiceBus critical error:\n{errorMessage}\nShutting down.";
Environment.FailFast(fatalMessage, exception);

The default callback should be overriden, if some custom code should be executed before exiting the process, such as persisting some in-memory data, flushing the loggers, etc. Refer to the Critical Errors article for more information.

Performance Counters

SLA violation countdown

In the NServiceBus Host the SLA violation countdown counter is enabled by default. But the value can be configured either by the above API or using a EndpointSLAAttribute on the instance of IConfigureThisEndpoint.

Edit
[EndpointSLA("00:03:00")]
public class EndpointConfig :
    IConfigureThisEndpoint
{

When Endpoint Instance Starts and Stops

Classes that plug into the startup/shutdown sequence are invoked just after the endpoint instance has been started and just before it is stopped. This approach may be used for any tasks that need to execute with the same life-cycle as the endpoint instance.

Edit
public class Bootstrapper :
    IWantToRunWhenBusStartsAndStops
{

    public void Start()
    {
        // Do startup actions here.
    }

    public void Stop()
    {
        // Do cleanup actions here.
    }
}

Samples

Related Articles


Last modified