Getting Started
Architecture
NServiceBus
Transports
Persistence
ServiceInsight
ServicePulse
ServiceControl
Monitoring
Samples

Sender-Side Distribution

Component: MSMQ Transport
NuGet Package: NServiceBus (7.x)

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

The 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>

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 messages. This results in both the Server1 and Server2 consoles processing the generated messages in an alternating fashion. This is because the messages are sent in a round-robin way to Server1 and Server2 by the client using the sender-side distribution feature.

Related Articles