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, 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:
- Host the gateway as a stateless service, and use partition aware routing to forward messages to other parts of the cluster.
- Because the service instances are hosted behind a load balancer, it is required to configure the gateway channel address to use a URL with a 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.
var config = new NonDurableDeduplicationConfiguration();
var gatewayConfig = endpointConfiguration.Gateway(config);
gatewayConfig.AddReceiveChannel("http://+:25899/RemoteSite/");
gatewayConfig.AddReceiveChannel("http://gateway.mycorp.com:25900/RemoteSite/", isDefault: true);
- Open the correct port for the gateway on the cluster load balancer by specifying an
Endpoint
entry in the service manifest.
<Resources>
<Endpoints>
<Endpoint Protocol="http" Name="RemoteEndpoint" Type="Input" Port="25899" />
</Endpoints>
</Resources>
- 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.
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 Task<string> OpenAsync(CancellationToken cancellationToken)
{
var endpoint = serviceContext.CodePackageActivationContext.GetEndpoint("RemoteEndpoint");
var uriPrefix = $"{endpoint.Protocol}://+:{endpoint.Port}/RemoteSite/";
var result = uriPrefix.Replace("+", FabricRuntime.GetNodeContext().IPAddressOrFQDN);
return Task.FromResult(result);
}
}
- Make sure the host service is present on all Service Fabric cluster instances, by specifying -1 for the
InstanceCount
value.