Hosting Gateway with Service Fabric

Gateway hosted in Service Fabric does not support forwarding messages containing Databus properties.

When adopting Service Fabric, it's not uncommon that the Service Fabric hosted endpoints need to interact with endpoints outside of the cluster. This can get tricky especially when the endpoints inside Service Fabric are stateful. When integrating using sender side distribution, or when using the Service Fabric built in reverse proxy to expose the endpoints as web services, then the partition information needs to be provided by the consumer.

Alternatively the nservicebus gateway can be leveraged as an intermediary to solve this problem. It provides reliable request reply semantics, with deduplication, between sites.

To host the NServiceBus Gateway in an endpoint deployed to Service Fabric, the following has to be taken into account:

  1. Host the gateway as a [stateless service](/nservicebus/hosting/service-fabric/hosting/#stateful service), and use partition aware routing within to forward messages to other parts of the cluster.
  2. Because the service instance are hosted behind a load balancer, it is required to configure the gateway channel address to use a URL with wildcard. The reason is that the public IP address is the one from the cluster load balancer and will therefore differ from the one that the gateway communication listener will effectively be listening on.
2.x NServiceBus.Gateway
<configuration>
  <configSections>
    <section name="GatewayConfig"
             type="NServiceBus.Config.GatewayConfig, NServiceBus.Gateway"/>
  </configSections>
  <GatewayConfig>
    <Channels>
      <Channel Address="http://+:25899/RemoteSite/"
               ChannelType="Http"
               Default="true"/>
    </Channels>
  </GatewayConfig>
</configuration>
  1. Open the correct port for the gateway on the cluster load balancer by specifying an Endpoint entry in the service manifest.
2.x NServiceBus.Gateway
<Resources>
  <Endpoints>
    <Endpoint Protocol="http" Name="RemoteEndpoint" Type="Input" Port="25899" />
  </Endpoints>
</Resources>
  1. Add a second communication listener that returns the gateway address using the local FQDN instead of the + sign, so that service fabric instance can set up the correct ACL on the host machine.
2.x NServiceBus.Gateway
public class GatewayCommunicationListener : ICommunicationListener
{
    readonly StatelessServiceContext serviceContext;

    public GatewayCommunicationListener(StatelessServiceContext serviceContext)
    {
        this.serviceContext = serviceContext;
    }

    public void Abort()
    {
    }

    public Task CloseAsync(CancellationToken cancellationToken)
    {
        return Task.FromResult(true);
    }

    public async Task<string> OpenAsync(CancellationToken cancellationToken)
    {
        var endpoint = serviceContext.CodePackageActivationContext.GetEndpoint("RemoteEndpoint");

        string uriPrefix = $"{endpoint.Protocol}://+:{endpoint.Port}/RemoteSite/";

        return uriPrefix.Replace("+", FabricRuntime.GetNodeContext().IPAddressOrFQDN);
    }
}
  1. Make sure the host service is present on all service fabric cluster instances, by specifying -1 for the InstanceCount value.

Related Articles


Last modified