dan4291
dan4291

Reputation: 11

Call Service Fabric service from console application using WCF HTTPS endpoint

I have a service hosted in a Service Fabric cluster in Azure (not locally) and I'm trying to call a method in it using a console application on my local machine. Using WCF for communication, I have a HTTPS endpoint set up in my application on a specific port, and have configured load balancing rules for the port in the Azure portal. The cluster has 6 nodes and the application is the only one deployed on the cluster.

Have followed the ServiceFabric.WcfCalc on GitHub (link), which works on a local cluster using HTTP endpoints, but can't call a method on the service using HTTPS endpoints once it has been deployed. What do I need to do to get it working? Have tried following the example here but don't know how to configure this for HTTPS with a service on multiple nodes for a console application to access.

Thanks in advance.

EDIT Here's my client code which I am using to call the service method. I pass the fabric:/ URI into the constructor here.

public class Client : ServicePartitionClient<WcfCommunicationClient<IServiceInterface>>, IServiceInterface
{
    private static ICommunicationClientFactory<WcfCommunicationClient<IServiceInterface>> communicationClientFactory;

    static Client()
    {
        communicationClientFactory = new WcfCommunicationClientFactory<IServiceInterface>(
            clientBinding: new BasicHttpBinding(BasicHttpSecurityMode.Transport));
    }

    public Client(Uri serviceUri)
        : this(serviceUri, ServicePartitionKey.Singleton)
    { }

    public Client(
        Uri serviceUri,
        ServicePartitionKey partitionKey)
        : base(
            communicationClientFactory,
            serviceUri,
            partitionKey)
    { }


    public Task<bool> ServiceMethod(DataClass data)
    {
        try
        {
             //It hangs here
            return this.InvokeWithRetry((c) => c.Channel.ServiceMethod(data));
        }
        catch (Exception)
        {
            throw;
        }
    }
}

When debugging my console application on my local machine, the application hangs on the InvokeWithRetry call which calls the method in my service in Service Fabric. The application does not throw any exceptions and does not return to the debugger in Visual Studio.

Upvotes: 1

Views: 1281

Answers (2)

yoape
yoape

Reputation: 3315

The warning you see in Service Fabric is telling you that there is already another service registered to listen on port 443 on your nodes. This means that Service Fabric fails to spin up your service (since it throws an exception internally when it is trying to register the URL with http.sys). You can change the port for your service to something else that will not conflict with the existing service, e.g.:

<Resources>
  <Endpoint Name="CalculatorEndpoint" Protocol="https" Type="Input" Port="44330" />
</Endpoints>

If you log in to Service Fabric Explorer on https://{cluster_name}.{region}.cloudapp.azure.com:19080 you should be able to see what other applications and services are running there. If you expand services all the way down to node you should be able to see the registered endpoints, including ports, for existing services.

Bonus You can query the cluster using FabricClient for all registered endpoints

var fabricClient = new FabricClient();
var applicationList = fabricClient.QueryManager.GetApplicationListAsync().GetAwaiter().GetResult();
foreach (var application in applicationList)
{
    var serviceList = fabricClient.QueryManager.GetServiceListAsync(application.ApplicationName).GetAwaiter().GetResult();
    foreach (var service in serviceList)
    {
        var partitionListAsync = fabricClient.QueryManager.GetPartitionListAsync(service.ServiceName).GetAwaiter().GetResult();
        foreach (var partition in partitionListAsync)
        {
            var replicas = fabricClient.QueryManager.GetReplicaListAsync(partition.PartitionInformation.Id).GetAwaiter().GetResult();
            foreach (var replica in replicas)
            {
                if (!string.IsNullOrWhiteSpace(replica.ReplicaAddress))
                {
                    var replicaAddress = JObject.Parse(replica.ReplicaAddress);
                    foreach (var endpoint in replicaAddress["Endpoints"])
                    {
                        var endpointAddress = endpoint.First().Value<string>();
                        Console.WriteLine($"{service.ServiceName} {endpointAddress} {endpointAddress}");
                    }
}}}}}

Just run that with the proper FabricClient credentials (if it is a secured cluster) and you should see it listing all endpoints for all services there. That should help you find the one that has an endpoint for :443

Upvotes: 0

LoekD
LoekD

Reputation: 11470

  • Make sure you run every service instance /replica with a unique url.

  • Make sure you call the WebHttpBinding constructor using WebHttpSecurityMode.Transport.

  • Make sure you register the url using the same port number (443 likely) as in you service manifest endpoint declaration.

  • Make sure the endpoint is configured as HTTPS.

Upvotes: 0

Related Questions