在Service Fabric中,你在哪里设置和访问每个环境的运行时配置参数?

87
对于本地和云环境,我应该如何设置自定义设置或参数,例如Sql数据库、存储账户等资源...理想情况下,只需要在代码中调用一个参数名称来指向特定的数据库,而这个参数在本地或云环境的配置中是不同的。谢谢。

虽然我希望他们包含了实际使用配置的应用程序代码,但是微软在以下文章中向您展示如何设置它:https://learn.microsoft.com/en-us/azure/service-fabric/service-fabric-how-to-parameterize-configuration-files - Adam Plocher
3个回答

151

为了在本地和云端运行Service Fabric时有各自的环境变量,您需要执行以下操作:

  1. 将自定义配置部分和参数添加到Service/Actor项目的Settings.xml文件中(位于从项目根目录开始的\PackageRoot\Config\Settings.xml)。将参数留空,因为我们将在其他地方根据不同的环境设置这些参数。下面是一个示例。
<?xml version="1.0" encoding="utf-8" ?>
<Settings xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/2011/01/fabric">
<!-- Add your custom configuration sections and parameters here -->
    <Section Name="UserDatabase">
        <Parameter Name="UserDatabaseConnectionString" Value="" />
    </Section>
</Settings>
  1. 在您的Service Fabric项目的ApplicationManifest.xml文件中,每个包含的项目都会有一个<ServiceManifestImport>元素。在该元素下面将会有一个<ConfigOverrides>元素,在其中我们将声明哪些配置值将被本地和云xml文件中每个环境设置的值所替换。在同一ApplicationManifest.xml文件中,您需要添加在本地 和云xml文件中存在的参数,否则它们将在构建时被覆盖。

继续上面的示例,以下是如何设置:

<Parameters>
    <Parameter Name="ServiceName_InstanceCount" DefaultValue="-1" />
    <Parameter Name="UserDatabaseConnectionString" DefaultValue="" />
</Parameters>
<ConfigOverrides>
    <ConfigOverride Name="Config">
        <Settings>
            <Section Name="UserDatabase">
                <Parameter Name="UserDatabaseConnectionString" Value="[UserDatabaseConnectionString]" />
            </Section>
        </Settings>
    </ConfigOverride>
</ConfigOverrides>
在 Service Fabric 项目中的 ApplicationParameters 目录下的 local.xml 和 cloud.xml 文件中,您可以这样指定环境特定变量。
<?xml version="1.0" encoding="utf-8"?>
<Application xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Name="fabric:/AppFabricName.ServiceFabric" xmlns="http://schemas.microsoft.com/2011/01/fabric">
    <Parameters>
        <Parameter Name="ServiceName_InstanceCount" Value="1" />
        <Parameter Name="UserDatabaseConnectionString" Value="Server=(localdb)\MsSqlLocalDb;Database=Users;User=ReadOnlyUser;Password=XXXXX;" />
    </Parameters>
</Application>
  1. 最后,在您的Service/Actor中,可以如下访问这些按环境划分的配置变量。
var configurationPackage = Context.CodePackageActivationContext.GetConfigurationPackageObject("Config");

var connectionStringParameter = configurationPackage.Settings.Sections["UserDatabase"].Parameters["UserDatabaseConnectionString"];

106
我可以说“呸”吗!这个简单的基于环境设置实在是太复杂了。旧金山团队需要花点心思来开发它。 - BrettRobi
8
过早提问。 这里的评论: https://azure.microsoft.com/en-us/documentation/articles/service-fabric-manage-multiple-environment-app-configuration/ 指向了使用以下内容: CodePackageActivationContext activationContext = FabricRuntime.GetActivationContext(); - Steve
14
比起实际文档,这个要好得多,谢谢!同时也同意这很复杂……修复一下吧,SF团队! - naspinski
2
我遇到了一个问题,这些设置没有被覆盖。你必须在ServiceManifestImportApplicationManifest的子级)上面定义参数,但是ConfigOverrides必须放在它里面(ServiceManifestImport的子级)。 - Mardoxx
有没有办法从自托管的exe中访问这些变量?似乎无法访问“Context”。 - Steve
显示剩余12条评论

42

您可以像其他应用程序一样使用环境变量,这在服务织物中的客户可执行文件中也适用,不同于settings.xml,因为它需要内置服务织物运行时。

在您的应用程序中,您可以使用Environment类上的GetEnvironmentVariable方法访问环境变量,就像任何其他.net应用程序一样:

var baseUri = Environment.GetEnvironmentVariable("SuperWebServiceBaseUri");

接下来我们需要设置一些默认的环境变量值,这是通过服务的ServiceManifest.xml清单文件完成的。

<?xml version="1.0" encoding="utf-8" ?>
<ServiceManifest Name="MyServicePkg" Version="1.0.0" xmlns="http://schemas.microsoft.com/2011/01/fabric" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <!-- snip -->
    <CodePackage Name="Code" Version="1.0.0">
        <!-- snip -->
        <EnvironmentVariables>
            <EnvironmentVariable Name="SuperWebServiceBaseUri" Value="http://localhost:12345"/>
        </EnvironmentVariables>
    </CodePackage>
    <!-- snip -->
</ServiceManifest>

这些环境变量可以在ApplicationManifest.xml文件中使用以下代码进行覆盖:

<?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="ChileTargetType" ApplicationTypeVersion="1.0.0" xmlns="http://schemas.microsoft.com/2011/01/fabric">
    <Parameters>
        <!-- snip -->
    </Parameters>
    <ServiceManifestImport>
        <ServiceManifestRef ServiceManifestName="MyServicePkg" ServiceManifestVersion="1.0.0" />
        <EnvironmentOverrides CodePackageRef="Code">
            <EnvironmentVariable Name="SuperWebServiceBaseUri" Value="https://the-real-live-super-base-uri.com/"/>
        </EnvironmentOverrides>
    </ServiceManifestImport>
    <!-- snip -->
</ApplicationManifest>

然后,就像任何其他应用程序清单设置一样,可以使用local.xmlcloud.xml对其进行参数化。

<?xml version="1.0" encoding="utf-8"?>
<Application xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Name="fabric:/AppFabricName.ServiceFabric" xmlns="http://schemas.microsoft.com/2011/01/fabric">
    <Parameters>
        <Parameter Name="MyService_SuperWebServiceBaseUri" Value="https://another-base-uri.com/" />
    </Parameters>
</Application>

那么我们就需要更新 ApplicationManifest.xml 来支持这些参数;

<?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="ChileTargetType" ApplicationTypeVersion="1.0.0" xmlns="http://schemas.microsoft.com/2011/01/fabric">
    <Parameters>
        <Parameter Name="MyService_SuperWebServiceBaseUri" DefaultValue="https://the-real-live-super-base-uri.com/" />
    </Parameters>
    <ServiceManifestImport>
        <ServiceManifestRef ServiceManifestName="MyServicePkg" ServiceManifestVersion="1.0.0" />
        <EnvironmentOverrides CodePackageRef="Code">
            <EnvironmentVariable Name="SuperWebServiceBaseUri" Value="[MyService_SuperWebServiceBaseUri]"/>
        </EnvironmentOverrides>
    </ServiceManifestImport>
    <!-- snip -->
</ApplicationManifest>

2
更简洁的设置环境变量方式 - hungryMind
2
这个链接也对我有帮助:http://www.binaryradix.com/2016/10/reading-from-configuration-within-azure.html - Darrel K.

9
上面的答案已经很好地解释了如何完成这一过程。我想补充说明一下,为什么它是“复杂的”:

必须这样做,因为服务旨在是自包含的。它们应该在链接到任何应用程序时默认运行。独立于应用程序的清单。因此,服务只能依赖于参数,在其自己的配置中至少是预定义的。

然后,这些预设可以被应用程序覆盖。这是唯一通用的方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接