单个 ServiceManifest.xml 文件是否可以有两个 "ServiceManifests"

Is it possible to have two "ServiceManifests" for a single ServiceManifest.xml file

我想知道是否有人可以帮助我解决一些关于 Azure Service Fabric 的 ServiceManifest.xml 和 ApplicationManifest.xml 文件的问题。

背景

我正在使用依赖于 Azure Service Fabric 技术的 C# 多服务应用程序。我们对整个应用程序使用 ApplicationManifest.xml 文件,对每个单独的服务使用 ServiceManifest.xml 文件。我们的 ServiceManifest 遵循以下模板:

<?xml version="1.0" encoding="utf-8"?>
<ServiceManifest Name="MyServiceName.ConfigurationServicePkg"
                 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>
    <!-- This is the name of your ServiceType. 
         This name must match the string used in RegisterServiceType call in Program.cs. -->
    <StatelessServiceType ServiceTypeName="MyServiceName.Configuration" >
     <PlacementConstraints>requestManagerAllowed==true</PlacementConstraints>
     </StatelessServiceType>
  </ServiceTypes>

  <!-- Code package is your service executable. -->
  <CodePackage Name="Code" Version="1.0.0">
    <EntryPoint>
      <ExeHost>
        <Program>MyCompanyName.MyServiceName.Configuration.exe</Program>
        <WorkingFolder>CodePackage</WorkingFolder>
      </ExeHost>
    </EntryPoint>
    <EnvironmentVariables>
      <EnvironmentVariable Name="ASPNETCORE_ENVIRONMENT" Value=""/>
    </EnvironmentVariables>
  </CodePackage>

  <!-- Config package is the contents of the Config directoy under PackageRoot that contains an 
       independently-updateable and versioned set of custom configuration settings for your service. -->
  <ConfigPackage Name="Config" Version="1.0.0"/>

</ServiceManifest>

我们的服务(和整个解决方案)最近针对我们必须部署到的新环境进行了更名,同时仍然部署到旧环境。我们已将所有 .csproj 文件编辑为具有两个不同的程序集名称,具体取决于我们针对的构建配置,以便我们可以为新旧环境构建和发布二进制文件。

例如,我们的应用程序中有一个配置服务。使用旧的构建配置构建时,配置服务的 exe 将命名如下 OldCompanyName.OldServiceName.Configuration.exe

使用新的构建配置构建时,名称发生变化,看起来像 NewCompanyName.NewServiceName.Configuration.exe

问题

问题是我们仍然需要能够部署到新旧环境。尝试将我们的服务部署到新环境时,Service Fabric 使用配置服务的 ServiceManifest.xml 来确定它需要找到 OldCompanyName.OldServiceName.Configuration.exe 可执行文件作为该服务的入口点。但是,我们的解决方案必须使用新的构建配置来构建,因此所有的 exe 和 dll 都按照新的约定命名 NewCompanyName.NewServiceName.Configuration.exe.

由于无法找到服务的入口点,Service fabric 抛出以下异常:

The EntryPoint OldCompanyName.OldServiceName.Configuration.exe is not found.\r\nFileName: D:\..\..\AppType\..\OldCompanyName.OldServiceName.ConfigurationServicePkg\ServiceManifest.xml

我的问题

ServiceManifest.xml 是否支持根据使用的构建配置使用两个单独的 ServiceManifests?例如,我的第一个想法看起来像这样(非常粗糙的伪代码):

<?xml version="1.0" encoding="utf-8"?>
<!-- IF using old build configuration -->
<ServiceManifest Name="OldServiceName.ConfigurationServicePkg"
                 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>
    <!-- This is the name of your ServiceType. 
         This name must match the string used in RegisterServiceType call in Program.cs. -->
    <StatelessServiceType ServiceTypeName="OldServiceName.Configuration" >
     <PlacementConstraints>requestManagerAllowed==true</PlacementConstraints>
     </StatelessServiceType>
  </ServiceTypes>

  <!-- Code package is your service executable. -->
  <CodePackage Name="Code" Version="1.0.0">
    <EntryPoint>
      <ExeHost>
        <Program>OldCompanyName.OldServiceName.Configuration.exe</Program>
        <WorkingFolder>CodePackage</WorkingFolder>
      </ExeHost>
    </EntryPoint>
    <EnvironmentVariables>
      <EnvironmentVariable Name="ASPNETCORE_ENVIRONMENT" Value=""/>
    </EnvironmentVariables>
  </CodePackage>

  <!-- Config package is the contents of the Config directoy under PackageRoot that contains an 
       independently-updateable and versioned set of custom configuration settings for your service. -->
  <ConfigPackage Name="Config" Version="1.0.0"/>

</ServiceManifest>

<!-- If using NEW build configuration -->
<ServiceManifest Name="NewServiceName.ConfigurationServicePkg"
                 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>
    <!-- This is the name of your ServiceType. 
         This name must match the string used in RegisterServiceType call in Program.cs. -->
    <StatelessServiceType ServiceTypeName="NewServiceName.Configuration" >
     <PlacementConstraints>requestManagerAllowed==true</PlacementConstraints>
     </StatelessServiceType>
  </ServiceTypes>

  <!-- Code package is your service executable. -->
  <CodePackage Name="Code" Version="1.0.0">
    <EntryPoint>
      <ExeHost>
        <Program>NewCompanyName.NewServiceName.Configuration.exe</Program>
        <WorkingFolder>CodePackage</WorkingFolder>
      </ExeHost>
    </EntryPoint>
    <EnvironmentVariables>
      <EnvironmentVariable Name="ASPNETCORE_ENVIRONMENT" Value=""/>
    </EnvironmentVariables>
  </CodePackage>

  <!-- Config package is the contents of the Config directoy under PackageRoot that contains an 
       independently-updateable and versioned set of custom configuration settings for your service. -->
  <ConfigPackage Name="Config" Version="1.0.0"/>

</ServiceManifest>

基本上,我只需要一些方法让现有 ServiceManifest.xml 文件有条件地针对不同命名的入口点,具体取决于正在使用的构建配置(我们正在部署到哪个环境)。关于如何实现这一点有什么想法吗?

如果您正在使用管道,(如 pipelines feature Azure DevOps), you can use a tokenizer 使用变量或变量组替换不同环境的占位符字符串。

您将创建一个带有分隔占位符的服务清单模板(例如 {{key}}),将它们替换为您 运行(旧的或新的)的特定构建,然后构建包.

模板如下所示:

  <!-- Code package is your service executable. -->
  <CodePackage Name="Code" Version="1.0.0">
    <EntryPoint>
      <ExeHost>
        <Program>{{companyname}}.Configuration.exe</Program>
        <WorkingFolder>CodePackage</WorkingFolder>
      </ExeHost>
    </EntryPoint>
  </CodePackage>

创建一个名为 'companyname' 的 Azure DevOps 变量,值为 'NewCompanyName.NewServiceName'。

标记化后,文件将如下所示:

  <!-- Code package is your service executable. -->
  <CodePackage Name="Code" Version="1.0.0">
    <EntryPoint>
      <ExeHost>
        <Program>NewCompanyName.NewServiceName.Configuration.exe</Program>
        <WorkingFolder>CodePackage</WorkingFolder>
      </ExeHost>
    </EntryPoint>
  </CodePackage>

在您的服务项目中添加第二个服务清单文件(不同的名称包含您需要的所有更改)。然后编辑服务项目文件:

 <ItemGroup  Condition="'$(Configuration)'=='Config2'">
  <None Remove="PackageRoot\ServiceManifest.xml" />
 </ItemGroup>
 <ItemGroup  Condition="'$(Configuration)'=='Config1'">
   <None Remove="PackageRoot\OtherServiceManifest.xml" />
 </ItemGroup>

在服务结构应用程序项目中,添加第二个应用程序清单文件(将引用其他服务清单)。然后编辑项目文件:

   <ItemGroup  Condition="'$(Configuration)'=='Config1'">
     <None Include="ApplicationPackageRoot\ApplicationManifest.xml" />
   </ItemGroup>
   <ItemGroup  Condition="'$(Configuration)'=='Config2'">
     <None Include="ApplicationPackageRoot\OtherApplicationManifest.xml" />
   </ItemGroup>