Search code examples
azure-service-fabric

Service Fabric - Are Endpoint definitions required for service remoting?


I'm trying to understand in what scenarios endpoint definitions are required in the ServiceManifest. I have a stateful service with the multiple service remoting listeners defined. My implementation of CreateServiceReplicaListeners:

        protected override IEnumerable<ServiceReplicaListener> CreateServiceReplicaListeners()
        {
            return new[]
            {
                new ServiceReplicaListener(context => this.CreateServiceRemotingListener(context)),
                new ServiceReplicaListener(context =>
                                           {
                                               return new FabricTransportServiceRemotingListener(context,
                                                                                                 new CustomService<string>(),
                                                                                                 new FabricTransportRemotingListenerSettings
                                                                                                 {
                                                                                                     EndpointResourceName = "ustdfdomgfasdf"
                                                                                                 });
                                           }, name: "CustomListener")
            };
        }

The endpoint resource name for the custom listener is garbage. I have not defined that endpoint in the service manifest's resources:

<Resources>
    <Endpoints>
      <Endpoint Name="ServiceEndpoint" />
      <Endpoint Name="ReplicatorEndpoint" />
    </Endpoints>
  </Resources>

However, in testing I find I'm still able to get a proxy to CustomListener:

InventoryItem i = new InventoryItem(description, price, number, reorderThreshold, max);

var applicationInstance = FabricRuntime.GetActivationContext().ApplicationName.Replace("fabric:/", String.Empty);            
var inventoryServiceUri = new Uri("fabric:/" + applicationInstance + "/" + InventoryServiceName);

//Doesn't fail
ICustomService customServiceClient = ServiceProxy.Create<ICustomService>(inventoryServiceUri, 
    i.Id.GetPartitionKey(), 
    listenerName: "CustomListener");

//Still doesn't fail
var added = await customServiceClient.Add(1, 2);

To me, this indicates endpoint definitions aren't required for service remoting as long as the endpoint and listener names are unique. Is that so? If not, why does my example work?


Solution

  • Endpoints are required to tell service fabric to allocate ports in the node for the services being started on that node, this will prevent port collision when many services are opening ports in the node.

    Once allocated, these are create as Environment Variables in the service process, something like: Fabric_Endpoint_<EndpointName> : port

    When you create the Listeners, they are responsible to open the ports, generally using the ports allocated via Endpoints, but not prevents you creating a custom listener to Open any port (If running with enough privilege to do so)

    CreateServiceRemotingListener(context) creates the default listeners

    EndpointResourceName setting tell which endpoint to be used by a listener, if not defined, DefaultEndpointResourceName setting is used as the default Endpoint, the default value is "ServiceEndpoint"

    What I am not sure to answer right now is: if EndpointResourceName is not found, it uses DefaultEndpointResourceName, I assume so, need to check the code to confirm that.

    When multiple listeners are using the same port, they generally have a path to identify each of them, something like: tcp://127.0.0.1:1234/endpointpath