Search code examples
azureasp.net-web-apiload-balancingazure-service-fabric

Using reverse proxy localhost not working on 5-node cluster in Azure Service Fabric


I have an API Gateway service in an Azure Service Fabric cluster which I use as a Gateway to my Service Fabric services.

This all works fine on my machine, and also in a 1-node cluster in Azure.

However, when I run it in a 5-node cluster, I get the error

System.Net.Http.HttpRequestException: 
An error occurred while sending the request. ---> 
System.Net.WebException: Unable to connect to the remote server 
System.Net.Sockets.SocketException: 
No connection could be made because the target machine actively refused it 127.0.0.1:19081

I know 19081 is the default reverse proxy port. I haven't seen any instructions anywhere about specifically unblocking this port, so I am assuming it's open.

I am confused about why 127.0.0.1 works in a 1-node cluster but not a 5-node cluster.

I think the issue may be that the service I am calling is not always going to be on the same node as the API gateway that the load balancer sends a request to.

How can I get around this?

My Price Service Fabric service has a single instance which could be on any node.

It is not an option for me to have multiple instances of my price service.

For info, here is the link I used:

You Tube Video

I am going to go back through it to see if I missed something.

Here is the code I am using to get the data:

var proxyUrl = $"http://My Service Fabric URL:{this._configSettings.ReverseProxyPort}/{url.Replace("fabric:/", "")}/api/{Area}/{method}{parameters}";
            Log.Information($"xUrl: {proxyUrl}");

            var response = await this._httpClient.GetAsync(proxyUrl).ConfigureAwait(false);

            var responseText = await response.Content.ReadAsStringAsync().ConfigureAwait(false);

            if (response.StatusCode != System.Net.HttpStatusCode.OK)
            {
                Log.Information($"{this.GetType().Name}: Error Response: {response.StatusCode}");

                return this.StatusCode((int) response.StatusCode);
            }

            Log.Information(this.GetType().Name + ": Called API");

Following the suggestion below, I now have the code to get the address:

   var resolver = ServicePartitionResolver.GetDefault();
        var partition = await resolver.ResolveAsync(_serviceContext.ServiceName, ServicePartitionKey.Singleton, CancellationToken.None).ConfigureAwait(false);
        var endpoints = JObject.Parse(partition.GetEndpoint().Address)["Endpoints"];
        var address = endpoints[""].ToString().TrimEnd('/');

        var proxyUrl = $"{address}:{this._configSettings.ReverseProxyPort}/{url.Replace("fabric:/", "")}/api/{Area}/{method}{parameters}";

This gives http://localhost:8081.

How does this fit in with the reverse proxy port?

Cheers

Paul


Solution

  • You get this error because the service which listens this port is deployed on another node. There is two ways to achieve your goal:

    1. Use fullname of your service fabric cluster like http://mycluster.eastus.cloudapp.azure.com:19081/
    2. Use Naming Service to resolve endpoint of your service:

    Example of resolving code:

    var resolver = ServicePartitionResolver.GetDefault();
    var endpoints = resolver.ResolveAsync(service.ServiceName, ServicePartitionKey.Singleton, CancellationToken.None).Result;