Understanding webroles
Up until now I’ve only discussed worker roles, deliberatly, as they are relatively straight forward to use in combination with NServiceBus.
Webroles however are a bit different when it comes to NServiceBus hosting, not that it is per se more difficult to do so, but you need to understand how webroles work to avoid weird effects when running NServiceBus inside them.
There are 2 flavors of webroles, Hosted Web Core and Full IIS, and it makes a difference to host NServiceBus depending on which one you use as their process model differs quite a lot.

If you’re webrole uses HWC there will be only 1 process hosting your assemblies, representing the web role. In this scenario there is no difference between a web and worker and you can simply host an NServiceBus endpoint inside of it the same way.
But in Full IIS mode, which is the default, you need to know that 1 webrole project will result in 2 processes which share the same assemblies. One of the processes is the role host, the other is an IIS website which will actually serve requests. But as they share assemblies, combined with the automagical nature of the NServiceBus hosting model, this would result in 2 processes with identical messagehandlers and configuration, not what you want.
Therefore we only support the hosting model for the role hosts (represented by webrole.cs in a webrole project). For the IIS website you have to configure the bus manually, using the Configure class and it’s extension methods.
Configuring a role manually has also been shown a lot in previous posts, but for completion sake I’ll show it again.
Configure.WithWeb() // With allows you to control the assemblies to load
.Log4Net()
.DefaultBuilder()
.AzureConfigurationSource()
.AzureMessageQueue()
.JsonSerializer()
.AzureSubcriptionStorage()
.UnicastBus()
.LoadMessageHandlers()
.IsTransactional(true)
.CreateBus()
.Start();
Web workers
Now that you know that you can control the behavior of NServiceBus in both processes, you can create what we call ‘web workers’ in azure lingo. This are Windows Azure instances that host both webroles and worker roles. These are very interesting from a cost saving perspective, you can in fact host multiple website and workers when combining webworkers with NServiceBus’ dynamic azure host.
To set this up, you need to add a webrole.cs file to your webrole project in which you inherit from NServiceBus’ RoleEntryPoint and configure the endpoint AsA_Host. This will setup the role host to spin off child processes that act as workers, see my previous post on the details of how to do this. The host itself will not run a bus to avoid loading the website’s messagehandlers in it’s process space as these processes do share assemblies. (Remember! Selecting another role, like AsA_Worker, will load the messagehandlers)
In global.asax you can then configure the bus manually to be hosted in the website using the Configure class as stated above. All message handlers referenced from the webrole will be hosted in the IIS process and, as manual configuration ignores any IConfigureThisEndpoint implementation, you also avoid running a second dynamic host.
IIS 7.5
One small caveat when running in IIS version 7.5, which is installed on the latest azure OS families based on Windows Server 2008 R2, is that you cannot access either RoleEnvironment nor HttpContext early in the request lifecycle. Trying to configure NServiceBus at Application_Start will result in an exception as it does use these constructs internally.
An easy way to resolve this is to use .Net’s Lazy<T> to postpone initialization of the bus to the first Application_BeginRequest occurance in a thread safe manner:
private static readonly Lazy StartBus = new Lazy(ConfigureNServiceBus);
private static IBus ConfigureNServiceBus()
{
var bus = Configure.WithWeb()
...;
return bus;
}
protected void Application_BeginRequest()
{
Bus = StartBus.Value;
}
Want to get started with your own webworker?
Then check out the AzureHost sample in the NServiceBus trunk and build from there.
Happy coding!
Recent Comments