MSMQ to legacy Azure Service Bus Transport Bridge

This page refers to the deprecated legacy Azure Service Bus transport that uses the WindowsAzure.ServiceBus NuGet package. All users should migrate to the Azure Service Bus transport transport.

Endpoints running on different transports cannot exchange messages and require additional integration work.

Common examples include:

  • A hybrid solution that spans across endpoints deployed on-premises and in a cloud environment.
  • Departments within organization integrating their systems that use different messaging technologies for historical reasons.

Traditionally, such integrations would require native messaging or relaying. Bridging is an alternative, allowing endpoints to communicate over different transports without a need to get into low-level messaging technology code. With time, when endpoints can standardize on a single transport, bridging can be removed with a minimal impact on the entire system.

Prerequisites

An environment variable named AzureServiceBus.ConnectionString with the connection string for the Azure Service Bus namespace.

Azure Service Bus Transport

This sample uses the Azure Service Bus Transport (Legacy).

Code walk-through

This sample shows an integration between two endpoints running on two different transports, MsmqEndpoint endpoint running on MSMQ and AsbEndpoint running on Azure Service Bus.

Covered scenarios are:

  • Sending commands from Azure Service Bus endpoint to MSMQ endpoint.
  • Publishing events from MSMQ endpoint and subscribing to those events from Azure Service Bus endpoint.

Bridging

Endpoints are bridged using NServiceBus.Router. Bridge project is implemented as a standalone process that runs side-by-side with the bridged endpoints, MsmqEndpoint and AsbEndpoint.

Azure Service Bus endpoint configuration

In this example Azure Service Bus transport is configured to use the EndpointOrientedTopology (to learn more check the topologies documentation). This topology requires some additional steps to be properly bridged.

topology.RegisterPublisher(typeof(MyEvent), "Bridge");

Azure Service Bus endpoint is bridged via Bridge queue:

var routing = transport.Routing();
var bridge = routing.ConnectToBridge("Bridge");

Azure Service Bus topology

The routing of commands to the MSMQ endpoint is specified using bridge extension method:

bridge.RouteToEndpoint(typeof(MyCommand), "Samples.Azure.ServiceBus.MsmqEndpoint");
to access bridge extension method, project has to reference NServiceBus.Router.Connector NuGet package for NServiceBus 7 or NServiceBus.Bridge.Connector NuGet package for NServiceBus 6.

To subscribe to an event published by MSMQ endpoint, Azure Service Bus endpoint must register publishing endpoint using bridge extension method:

bridge.RegisterPublisher(typeof(MyEvent), "Samples.Azure.ServiceBus.MsmqEndpoint");

MSMQ endpoint configuration

MSMQ endpoint is bridged via Bridge queue:

MSMQ topology

Bridge configuration

Bridge process is connecting between MSMQ and Azure ServiceBus transports and provide any configuration settings required by any of the transports. For Azure Service Bus that would be a mandatory connection string and topology.

var bridgeConfiguration = new RouterConfiguration("Bridge");
#pragma warning disable 618
var azureInterface = bridgeConfiguration.AddInterface<AzureServiceBusTransport>("ASB", transport =>
#pragma warning restore 618
{
    //Prevents ASB from using TransactionScope
    transport.Transactions(TransportTransactionMode.ReceiveOnly);
    transport.ConnectionString(connectionString);

    // TODO: ASB requires serializer to be registered.
    // Currently, there's no way to specify serialization for the bridged endpoints
    // endpointConfiguration.UseSerialization<T>();
    var settings = transport.GetSettings();
    var serializer = Tuple.Create(new NewtonsoftSerializer() as SerializationDefinition, new SettingsHolder());
    settings.Set("MainSerializer", serializer);

    var topology = transport.UseEndpointOrientedTopology().EnableMigrationToForwardingTopology();
    topology.RegisterPublisher(typeof(OtherEvent), "Samples.Azure.ServiceBus.AsbEndpoint");
});
var msmqInterface = bridgeConfiguration.AddInterface<MsmqTransport>("MSMQ", transport =>
{
    transport.Transactions(TransportTransactionMode.ReceiveOnly);
});
msmqInterface.EnableMessageDrivenPublishSubscribe(new InMemorySubscriptionStorage());

//Configure the host of the MSMQ endpoint
msmqInterface.EndpointInstances.AddOrReplaceInstances("publishers", new List<EndpointInstance>
{
    new EndpointInstance("Samples.Azure.ServiceBus.MsmqEndpoint").AtMachine(Environment.MachineName)
});

bridgeConfiguration.AutoCreateQueues();

var staticRouting = bridgeConfiguration.UseStaticRoutingProtocol();

staticRouting.AddForwardRoute(
    incomingInterface: "MSMQ",
    outgoingInterface: "ASB");

staticRouting.AddForwardRoute(
    incomingInterface: "ASB",
    outgoingInterface: "MSMQ");

A bridge is created, started, and should be executed as long as bridging is required.

This sample use a simple InMemorySubscriptionStorage. In production SqlSubscriptionStorage (included in the NServiceBus.Router package) or custom persistent subscription storage should be used to prevent message loss.
var bridge = Router.Create(bridgeConfiguration);

await bridge.Start().ConfigureAwait(false);

Console.WriteLine("Press any key to exit");
Console.ReadKey();

await bridge.Stop().ConfigureAwait(false);

Related Articles


Last modified