Message routing - NServiceBus - Particular Software
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:
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 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.
As described in messages, events and commands, 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.
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. The per-namespace routes override assembly-level routes and the per-type routes override both namespace and assembly routes.
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.
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.
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.
EndpointOrientedTopologyrequires publishers names to be configured.
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
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.
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
MessageEndpointMappings routing configuration can take advantage of message inheritance: base types "inherit" routes from the derived types (opposite to member inheritance in .NET). If both
EventTwo inherit from
BaseEvent, when subscribing to
BaseEvent the subscription messages are sent to publishers of both
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.