Sender-Side Distribution

Component: MSMQ Transport
NuGet Package NServiceBus (6.x)
This sample is only relevant for the MSMQ transport. The other broker-based transports scale out using the competing consumer pattern. The functionality in this sample is available for NServiceBus Core Versions 6 and above.

Sometimes a single endpoint for handling messages is not enough, so there is a need to scale out. The following sample demonstrates how to scale out existing MSMQ message processing by distributing messages on the sender side.

Code walk-through

There are several projects in the solution.

Server1 and Server2

These two projects are identical and show the scale out in action from within Visual Studio. In a real-world scenario, there would be a single server project that is deployed to multiple paths and/or machines.

Instance ID

Following snippet instructs NServiceBus to get the instance ID from the appSettings configuration section.

var discriminator = ConfigurationManager.AppSettings["InstanceId"];
endpointConfiguration.MakeInstanceUniquelyAddressable(discriminator);
<appSettings>
  <add key="InstanceId" value="instance1"/>
</appSettings>
Never hard-code instance IDs because they are mostly operations concern and operations people should be able to modify them without the need to recompile the source code.

Handling code

public class DoSomethingHandler :
    IHandleMessages<DoSomething>
{
    static ILog log = LogManager.GetLogger<DoSomethingHandler>();

    public Task Handle(DoSomething message, IMessageHandlerContext context)
    {
        log.Info($"Message {message.SequenceId} received.");
        return Task.CompletedTask;
    }
}

Messages

Contains message definitions shared by the server and the client.

Client

The client configures the logical routing:

routingSettings.RouteToEndpoint(
    messageType: typeof(DoSomething),
    destination: "Samples.SenderSideScaleOut.Server");

In addition to the logical routing, the client also uses an instance mapping file to tell NServiceBus about the specific instances of the server. This is done as follows:

var instanceMappingFile = routingSettings.InstanceMappingFile();
instanceMappingFile.FilePath("routes.xml");
<endpoints>
  <endpoint name="Samples.SenderSideScaleOut.Server">
    <!-- Scaled-out endpoint -->
    <instance discriminator="instance1" />
    <instance discriminator="instance2" />
  </endpoint>
</endpoints>

Running the code

Start the solution with all the console applications (Server1, Server2, Client) as startup applications.

In the Client console, press enter a few times to generate message load. This results in both the Server1 and Server2 consoles processing the generated message load in an alternating fashion. This is because the messages are sent in a round-robin fashion to Server1 and Server2 by the client using the sender-side distribution feature.

Samples

Related Articles


Last modified