NService.Router
community package and should be considered for multi-transport operations.The sample demonstrates how NServiceBus.Router can be used to connect endpoints that use different transports, in this case MSMQ and RabbitMQ.
Prerequisites
- Ensure an instance of RabbitMQ is running and accessible.
- Ensure that MSMQ has been installed.
Running the project
- Start the projects in debug mode.
- Press
enter
in the Client console a couple of times. - Observe the
RequestHandler
logging processed message IDs in the Server window. - Observe the
ReplyHandler
logging processed message IDs in the Client window. - Observe the
EventHandler
logging processed message IDs in the Client window.
Code walk-through
The solution consists of four projects.
Shared
The Shared project contains the message contracts.
Client
The Client project contains an NServiceBus endpoint that runs the MSMQ transport. It is configured to route MyMessage
request through the router to the Server endpoint. It is also configured to route subscribe messages for MyEvent
messages through the router.
var bridge = transport.Routing().ConnectToRouter("Samples.Router.MixedTransports.Router");
bridge.RouteToEndpoint(typeof(MyMessage), "Samples.Router.MixedTransports.Server");
bridge.RegisterPublisher(typeof(MyEvent), "Samples.Router.MixedTransports.Server");
Server
The Server project contains an NServiceBus endpoint that runs the RabbitMQ transport. It processes MyMessage
messages. As a result it publishes MyEvent
events as well as replies directly to the Client with MyResponse
.
log.Info($"Request {message.Id}");
await context.Publish(new MyEvent
{
Id = message.Id
}).ConfigureAwait(false);
await context.Reply(new MyReply
{
Id = message.Id
}).ConfigureAwait(false);
Both of these messages travel through the router but because they are not direct sends, the Server does not require any router configuration.
Router
The Router project sets up a bi-directional connection between MSMQ and RabbitMQ.
var routerConfig = new RouterConfiguration("Samples.Router.MixedTransports.Router");
var msmqInterface = routerConfig.AddInterface<MsmqTransport>("MSMQ", t => { });
msmqInterface.EnableMessageDrivenPublishSubscribe(new InMemorySubscriptionStorage());
var rabbitMQInterface = routerConfig.AddInterface<RabbitMQTransport>("RabbitMQ", t =>
{
t.ConnectionString("host=localhost");
t.UseConventionalRoutingTopology();
});
var staticRouting = routerConfig.UseStaticRoutingProtocol();
staticRouting.AddForwardRoute("MSMQ", "RabbitMQ");
routerConfig.AutoCreateQueues();
The router forwards the MyMessage
messages based on the destination endpoint specified by the Client in the message headers. When forwarding, it replaces the NServiceBus.
header with its own header so that MyReply
messages sent by the Server are automatically sent to the router and then forwarded to the ultimate recipient, the Client.
The router translates the incoming subscribe messages from the Client to the native RabbitMQ subscription action (creating the exchange hierarchies) and uses its own subscription store to keep track of subscribers on the MSMQ side. When an event is published by the Server it is published to the router using RabbitMQ transport native mechanisms and then forwarded to the Client based on the data in the subscription store.