Using NServiceBus distributor
NServiceBus 2.0 RTM doesn’t contain a sample of how to use one of its nicest features: the distributor. By reading this blog post you will learn how to modify the FullDuplex-sample so that it uses the distributor model.
Background
NserviceBus’ documentation contains a good article about the logic behind the distributor. Here’s one part from the documentation which nicely sums it up:
You can think of the distributor as something like a load balancer - it distributes the messages coming to it to a number of other machines. This kind of physical one-to-many communication is needed for scaling out the number of machines running for a given subscriber, but doesn't actually entail any pub/sub. Each subscriber gets its own distributor and each of them decides independently to which machine it will pass its messages.
Here’s a small picture to light things up. As you can see, when using the distributor, the client doesn’t talk directly with the server but instead it communicates with the distributor. Distributor then forwards the received message to one of its workers. All workers can be located on the same server or every worker can have a dedicated server.
Aim of this post
We’re going to modify the FullDuplex-sample, which is included with the NServiceBus package, to use the distributor. In the end we’re going to have one client, one distributor and two workers all communicating with each other. And before we proceed, here’s a spoiler: We only need to touch the configuration files.
1. Configuring the distributor
You can locate the NServiceBus distributor from Nservicebusprocessesdistributor. Open the configuration file NServiceBus.Distributor.dll.config and then… you can close it. There’s nothing in there which we need to change! You can immediately start the NServiceBus distributor by starting the NServiceBus.Host.exe. Make sure you don’t see any error messages.
2. Configuring the client
Next, open the FullDuple-sample and then locate the MyClient-project and the contained configuration file App.config. In this step we actually have to modify the configuration file but it’s a simple change. By default the UnicastBusConfig looks like this:
<span style="color: #606060" id="lnum1"> 1:</span> <UnicastBusConfig>
<span style="color: #606060" id="lnum2"> 2:</span> <MessageEndpointMappings>
<span style="color: #606060" id="lnum3"> 3:</span> <add Messages=<span style="color: #006080">"MyMessages"</span> Endpoint=<span style="color: #006080">"MyServerInputQueue"</span> />
<span style="color: #606060" id="lnum4"> 4:</span> </MessageEndpointMappings>
<span style="color: #606060" id="lnum5"> 5:</span> </UnicastBusConfig>
But like we’ve have learned, the client shouldn’t try to send the messages to the server (worker) but to the distributor. And to be specific, the messages should go to the distributor’s DataInputQueue. Because we didn’t change anything in the distributor’s default configuration file, the client should send the messages to a queue named distributorDataBus. So let’s make the change:
<span style="color: #606060" id="lnum1"> 1:</span> <UnicastBusConfig>
<span style="color: #606060" id="lnum2"> 2:</span> <MessageEndpointMappings>
<span style="color: #606060" id="lnum3"> 3:</span> <add Messages=<span style="color: #006080">"MyMessages"</span> Endpoint=<span style="color: #006080">"distributorDataBus"</span> />
<span style="color: #606060" id="lnum4"> 4:</span> </MessageEndpointMappings>
<span style="color: #606060" id="lnum5"> 5:</span> </UnicastBusConfig>
Now you can start the client. Wait for it to initialize and then use enter to send a message. You should see some activity on the distributor. But we’re still missing our workers so the client isn’t getting the replies it is waiting for.
3. Configuring the worker
We must change the worker’s configuration so that it can make itself available to the distributor. And again, the changes are small. First, give the worker a dedicated queue by changing the InputQueue to “worker”. Your MsmqTransportConfig-section should now look like this:
<span style="color: #606060" id="lnum1"> 1:</span> <MsmqTransportConfig
<span style="color: #606060" id="lnum2"> 2:</span> InputQueue=<span style="color: #006080">"worker"</span>
<span style="color: #606060" id="lnum3"> 3:</span> ErrorQueue=<span style="color: #006080">"error"</span>
<span style="color: #606060" id="lnum4"> 4:</span> NumberOfWorkerThreads=<span style="color: #006080">"1"</span>
<span style="color: #606060" id="lnum5"> 5:</span> MaxRetries=<span style="color: #006080">"5"</span>
<span style="color: #606060" id="lnum6"> 6:</span> />
Then, in the UnicastBusConfig-section, type in the DistributorControlAddress and the DistributorDataAddress. You can find the correct values from the distributor’s configuration. Because we’re using the default configuration, the worker’s configuration should end up looking this:
<span style="color: #606060" id="lnum1"> 1:</span> <UnicastBusConfig
<span style="color: #606060" id="lnum2"> 2:</span> DistributorControlAddress=<span style="color: #006080">"distributorControlBus"</span>
<span style="color: #606060" id="lnum3"> 3:</span> DistributorDataAddress=<span style="color: #006080">"distributorDataBus"</span>>
<span style="color: #606060" id="lnum4"> 4:</span> <MessageEndpointMappings />
<span style="color: #606060" id="lnum5"> 5:</span> </UnicastBusConfig>
And that’s it. You can now start the server and after the initialization, the client should receive its reply. Keep pressing enter in the client console and you should see messages flying around.
4. Creating an another worker
We’re almost there. The aim was to have two workers so we’re going to do just that. Here’s how to do this:
- Create a copy of the worker’s bin-folder (see picture).
- Open the configuration file from the newly copied folder.
- Change the InputQueue to “worker2”.
- Start the worker.
Now when you again start hitting the enter-key in the client console you should see NServiceBus distributor in action: messages are handled by both of the workers. Here’s a picture from my screen after I had hit the enter for twenty times:
Conclusion
Modifying the default FullDuplex sample to use the NServiceBus distributor required only some small changes to the configuration files. In future posts, I’m hoping to expand on the topics related to the NServiceBus configuration: in this post we just skimmed through the changes to get things running.
Links:
- NServiceBus – Distributor and Load Balancing
- Distributed Processing with NServiceBus (good introduction to the distributor’s configuration file)