Message routing

Component: NServiceBus | Nuget: NServiceBus (Version: 6.x)

Routing concepts

Routing subsystem is responsible for finding destinations for the messages. In most cases the sending code should not care about the destination of the message being sent:

Edit
var endpointInstance = await Endpoint.Start(endpointConfiguration)
    .ConfigureAwait(false);
var message = new MyMessage();
await endpointInstance.Send(message)
    .ConfigureAwait(false);

Based on the type of the message the routing provides the destination address.

NServiceBus routing consists of two layers, logical and physical. Logical routing defines which logical endpoint should receive a given outgoing message. Physical routing defines to which actual physical instance of the selected endpoint should the message be delivered. While logical routing is a developer's concern, physical routing is controlled by operations.

Broker transports handle the physical routing automatically. Other transport might require specific configuration. To read more about physical routing with MSMQ go here.

Command routing

As described here, NServiceBus distinguishes several types of messages. Command messages are always routed to a single logical endpoint.

Command routing can be configured in code. The routing API root is attached to the transport configuration object because some routing APIs are transport-specific. The routes can be specified on assembly, namespace or specific type level.

Edit
var transportExtensions = endpointConfiguration.UseTransport<MyTransport>();

var routing = transportExtensions.Routing();
routing.RouteToEndpoint(
    assembly: typeof(AcceptOrder).Assembly,
    destination: "Sales");

routing.RouteToEndpoint(
    assembly: typeof(AcceptOrder).Assembly,
    @namespace: "PriorityMessages",
    destination: "Preferred");

routing.RouteToEndpoint(
    messageType: typeof(SendOrder),
    destination: "Sending");

The per-namespace routes override assembly-level routes and the per-type routes override both namespace and assembly routes.

Routing engine prevents ambiguous routes so if route information comes from more than one source (e.g. code API and configuration file) user has to make sure the type specifications do not overlap. Otherwise an exception will be thrown preventing an endpoint from starting up.

Command routing can also be configured in a configuration section.

Each entry in the collection has to specify the assembly where the messages are defined. In addition to that, a type name or the namespace name can be also specified for additional filtering.

For backwards compatibility a Messages attribute can be used instead of Type and Namespace attributes.
Edit
<configuration>
  <configSections>
    <section name="UnicastBusConfig"
             type="NServiceBus.Config.UnicastBusConfig, NServiceBus.Core"/>
  </configSections>
  <UnicastBusConfig>
    <MessageEndpointMappings>
      <add Assembly="MyMessages" 
           Endpoint="Sales" />

      <add Assembly="MyMessages"
           Namespace="PriorityMessages"
           Endpoint="Preferred" />

      <add Assembly="MyMessages"
           Type="MyMessages.SendOrder"
           Endpoint="Sending" />
    </MessageEndpointMappings>
  </UnicastBusConfig>
</configuration>

The per-namespace routes override assembly-level routes and the per-type routes override both namespace and assembly routes.

Overriding the destination

In specific cases, like sending to self or to a particular queue (e.g. for integration purposes), the routing configuration can be overridden when sending a given message. Refer to documentation on sending for further details.

Event routing

Events can be received by multiple logical endpoints, however even in case of scale out each event will be received only by one physical instance of any logical subscriber. Before the message is published and delivered, the subscriber has to express its interest in a given type of event.

Native

Multicast transports support Publish-Subscribe pattern natively. In this case the subscriber uses the APIs of the transport to create a route for a given subscribed message type.

Azure Service Bus EndpontOrientedTopology requires publishers names to be configured.

Message-driven

Other transports do not support Publish-Subscribe natively. These transports emulate the publish behavior by sending message to each subscriber directly. To do this, the publisher endpoint has to know its subscribers and subscribers have to notify the publisher about their interest in a given event type. The notification message (known as subscribe message) has to be routed to the publisher.

Subscribe message routing can be configured using code API

Edit
var transportExtensions = endpointConfiguration.UseTransport<MyTransport>();

var routing = transportExtensions.Routing();
routing.RegisterPublisher(
    assembly: typeof(OrderAccepted).Assembly,
    publisherEndpoint: "Sales");

routing.RegisterPublisher(
    assembly: typeof(OrderAccepted).Assembly,
    @namespace: "PriorityMessages",
    publisherEndpoint: "Preferred");

routing.RegisterPublisher(
    eventType: typeof(OrderSent),
    publisherEndpoint: "Sending");

Similarly to the command routing, more specific publisher registrations override less specific ones. The registrations need to be unambiguous.

Subscribe message routing can also be configured in a configuration section.

In the UnicastBusConfig/MessageEndpointMappings configuration section publishers are registered in the same way as the command destinations are defined. If a given assembly or namespace contains both events and commands, the mapping will recognize that fact and configure the routing correctly (both commands and subscribe messages will be routed to the destination specified in Endpoint attribute).

MessageEndpointMappings routing configuration can take advantage of message inheritence: base types "inherit" routes from the derived types (opposite to member inheritence in .NET). If both EventOne and EventTwo inherit from BaseEvent, when subscribing to BaseEvent the subscription messages are sent to publishers of both EventOne and EventTwo.

Reply routing

Replies are always routed based on the initial message ReplyTo header regardless of replier's routing configuration. Only the sender of the initial message can influence the routing of a reply. Refer to documentation on sending for further details.

Samples

  • Publish/Subscribe
    Publish/Subscribe, fault-tolerant messaging, and durable subscriptions.

Related Articles


Last modified