Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Service Fabric: are multiple service types allowed in ServiceManifest.xml

I'm trying to register multiple service-fabric services within a single exe (ServiceRuntime.RegisterServiceAsync). Is this supported? If so, how would I configure them?

Eg: ServiceManifest.xml supports multiple StatelessServiceType elements within ServiceTypes:

<?xml version="1.0" encoding="utf-8"?>
<ServiceManifest Name="EchoGatewayPkg"
                 Version="1.0.0"
                 xmlns="http://schemas.microsoft.com/2011/01/fabric"
                 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <ServiceTypes>
    <StatelessServiceType ServiceTypeName="Service1Type" >
    </StatelessServiceType>

    <StatelessServiceType ServiceTypeName="Service2Type" >
    </StatelessServiceType>
  </ServiceTypes>
...

and ApplicationManifest.xml does not support multiple StatelessService elements within DefaultServices/Service:

<?xml version="1.0" encoding="utf-8"?>
<ApplicationManifest xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ApplicationTypeName="EchoServiceType" ApplicationTypeVersion="1.0.0" xmlns="http://schemas.microsoft.com/2011/01/fabric">
  <Parameters>
    <Parameter Name="Service1_InstanceCount" DefaultValue="1" />
    <Parameter Name="Service2_InstanceCount" DefaultValue="1" />
  </Parameters>
  <ServiceManifestImport>
    <ServiceManifestRef ServiceManifestName="MyServicePkg" ServiceManifestVersion="1.0.0" />
    <ConfigOverrides />
  </ServiceManifestImport>
  <DefaultServices>
    <Service Name="MyService1">
      <StatelessService ServiceTypeName="Service1Type" InstanceCount="[Service1_InstanceCount]">
        <SingletonPartition />
      </StatelessService>
    </Service>
    <Service Name="MyService2">
      <StatelessService ServiceTypeName="Service2Type" InstanceCount="[Service2_InstanceCount]">
        <SingletonPartition />
      </StatelessService>
    </Service>
  </DefaultServices>
</ApplicationManifest>

Hence, this effectively spawns 2 processes, and each process' activation-context has both default service types listed (I would have expected only one with this configuration).

Any suggestions (on how to configure multiple service types within a single exe) or clarifications are welcome.

like image 437
cperras Avatar asked Jul 31 '16 19:07

cperras


1 Answers

Disregarding default services for a second..

Yes, this is how you get multiple service types to share a host process. You're seeing 2 processes because Service Fabric is placing those two service instances on different nodes and each one needs a host process. Try creating each service with InstanceCount="-1" to see the two types share host processes.

OK, back to default services. This is inherently confusing because application manifest and service manifest are only meant to describe type information, not instance information. But in order to create service instances by default when an application instance is created, you have to specify, declaratively, the instances and their parameters. So what you see under default services there in your example is the XML equivalent of:

PS > New-ServiceFabricService -Stateless -PartitionSchemeSingleton -InstanceCount 1 -ApplicationName fabric:/EchoService -ServiceName fabric:/EchoService/MyService1 -ServiceTypeName Service1Type

PS > New-ServiceFabricService -Stateless -PartitionSchemeSingleton -InstanceCount 1 -ApplicationName fabric:/EchoService -ServiceName fabric:/EchoService/MyService2 -ServiceTypeName Service2Type

So it doesn't make sense to have more than one StatelessService element in the Service element, because you're defining the service instances you want to create, along with the type and version of the service instance.

And just for posterity, this is the registration code that goes with the service manifest you posted:

internal static class Program
{
    private static void Main()
    {
        try
        {
            ServiceRuntime.RegisterServiceAsync("Service1Type",
                context => new Stateless1(context)).GetAwaiter().GetResult();

            ServiceRuntime.RegisterServiceAsync("Service2Type",
                context => new Stateless2(context)).GetAwaiter().GetResult();

            Thread.Sleep(Timeout.Infinite);
        }
        catch (Exception e)
        {
            ServiceEventSource.Current.ServiceHostInitializationFailed(e.ToString());
            throw;
        }
    }
}
}
like image 189
Vaclav Turecek Avatar answered Oct 04 '22 20:10

Vaclav Turecek