【问题标题】:Is it possible to have two "ServiceManifests" for a single ServiceManifest.xml file单个 ServiceManifest.xml 文件是否可以有两个“ServiceManifests”
【发布时间】:2022-01-17 01:16:25
【问题描述】:

我想知道是否有人可以帮助我解决一些关于 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 是否支持根据使用的构建配置有两个单独的 ServiceManifest?举个例子,我的第一个想法是这样的(非常粗略的伪代码):

<?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 文件根据正在使用的构建配置(我们正在部署的环境)有条件地定位不同命名的入口点。对于如何实现这一点有什么想法吗?

【问题讨论】:

    标签: c# xml azure-service-fabric service-fabric-stateless


    【解决方案1】:

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

     <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>
    

    【讨论】:

      【解决方案2】:

      如果您使用的是管道(如 pipelines 功能 Azure DevOps),您可以使用 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>
      

      【讨论】:

      • 感谢您的回复!这是个好主意,但不幸的是,我们还需要能够在本地构建和发布我们的服务结构集群,这不涉及使用 Azure 管道
      • 好吧,写一个small script 是可行的,它在本地执行此操作对吗?您甚至可以在调试版本中 call it
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-05-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多