Self Hosting in Azure Cloud Services

Component: NServiceBus
NuGet Package NServiceBus (6.x)

Running in development mode

  1. Start Azure Storage Emulator
  2. Run the solution
  3. Inspect Azure Storage Emulator Tables for SelfHostedEndpointsOutput table and its content for something like the following:
PartitionKeyRowKeyTimestampMessage
MyMessageHandler2017-09-19 10:19:082017-09-19T08:19:27.691ZGot MyMessage.

Results are sorted by Timestamp

Deploying endpoints

  1. Open a PowerShell console at the self-host\CloudServicesHost_{version} location. This location should contain PackageAndDeploy.ps1.
  2. Execute the PackageAndDeploy.ps1 PowerShell script to package and deploy multi-hosted endpoints to local emulator storage.

Running self-host in emulated Cloud Service

  1. Set HostCloudService to be the start-up project by right-clicking the project name in Visual Studio Solution Explorer, and selecting Set as StartUp Project option
  2. Run the solution
  3. Inspect Azure Storage Emulator tables for SelfHostedEndpointsOutput table and its content
To inspect multi-host role emulated file system navigate to C:\Users\%USERNAME%\AppData\Local\dftmp\Resources

Azure Compute Emulator leaves any processes spawned at run time in memory. Kill those once done with emulated Cloud Service execution by locating WaWorkerHost.exe process and killing all child processes named NServiceBus.Hosting.Azure.HostProcess.exe. The number of those processes will be the same as the number of endpoints (i.e. one) x the number of times Cloud Service was executed.

Cloud Service emulator can also be stopped from Compute Emulator UI. Compute Emulator UI can be accessed via the try icon on the taskbar. Within Compute Emulator UI, under Service Deployments tree select a deployment, right-click and select the Remove option. This will cleanly stop Cloud Service without leaving any processes in memory.

Code walk-through

This sample contains five projects:

  • HostWorker - Self-host endpoint deployed as worker role.
  • HostCloudService - Azure Cloud Service project to define and execute cloud service.

HostWorker project

HostWorker project uses the self-hosting capability to start an endpoint inside a worker role.

The snippet below illustrates how the OnStart method of RoleEntryPoint calls in a blocking way into an asynchronous start method.

public override bool OnStart()
{
    StartEndpoint().GetAwaiter().GetResult();
    return base.OnStart();
}

static async Task StartEndpoint()

A critical error action needs to be defined to restart the host when a critical error is raised.

configuration.DefineCriticalErrorAction(
    onCriticalError: context =>
    {
        if (Environment.UserInteractive)
        {
            // so that user can see on their screen the problem
            Thread.Sleep(10000);
        }

        var message = $"Critical error encountered:\n{context.Error}\nNServiceBus is shutting down.";
        LogManager.GetLogger(typeof(WorkerRole)).Fatal(message);
        Environment.FailFast(message, context.Exception);
        return Task.CompletedTask;
    });

To uniquely identify the host a custom name and display name need to be provided.

if (SafeRoleEnvironment.IsAvailable)
{
    var host = SafeRoleEnvironment.CurrentRoleName;
    var instance = SafeRoleEnvironment.CurrentRoleInstanceId;
    var displayName = $"{host}_{instance}";
    configuration
        .UniquelyIdentifyRunningInstance()
        .UsingNames(instance, host)
        .UsingCustomDisplayName(displayName);
}

Connection string can be loaded by leveraging the RoleEnvironment as shown below.

var connectionString = RoleEnvironment.GetConfigurationSettingValue("HostWorker.ConnectionString");
var persistence = configuration.UsePersistence<AzureStoragePersistence>();
persistence.ConnectionString(connectionString);
var transport = configuration.UseTransport<AzureStorageQueueTransport>();
transport.ConnectionString(connectionString);

HostCloudService project

The HostCloudService project defines self-host parameters for all environment (Local and Cloud in this sample)

<WorkerRole name="HostWorker" vmsize="Small">
  <ConfigurationSettings>
    <Setting name="HostWorker.ConnectionString" />
    <Setting name="Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString" />
  </ConfigurationSettings>
  <LocalResources>
    <LocalStorage name="endpoints" cleanOnRoleRecycle="true" sizeInMB="100" />
  </LocalResources>
</WorkerRole>

Values provided to execute sample against local Azure Storage emulator

<Role name="HostWorker">
  <Instances count="1" />
  <ConfigurationSettings>
    <Setting name="HostWorker.ConnectionString"
             value="UseDevelopmentStorage=true" />
    <Setting name="Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString"
             value="UseDevelopmentStorage=true" />
  </ConfigurationSettings>
</Role>

Related Articles

  • Shared Hosting in Azure
    Using Azure Cloud Services to host multiple NServiceBus endpoints on a shared pool of machines.

Last modified