通过 Service Fabric 项目进行调试时未使用环境变量

Posted

技术标签:

【中文标题】通过 Service Fabric 项目进行调试时未使用环境变量【英文标题】:Environment variables not being used when debugging through a Service Fabric project 【发布时间】:2016-12-30 18:48:24 【问题描述】:

在创建 ASP.NET Core 应用时,将为您设置一个名为 ASPNETCORE_ENVIRONMENT=Development 的环境变量,在调试时您会看到 IHostingEnvironment 设置为 Development

问题是,当我在为 Service Fabric 设置的解决方案中使用同一个项目时,环境变量似乎没有被注入,IHostingEnvironment 只返回“生产”。

我该如何解决这个问题?

注意:我在启动类中设置了一个断点来观察 IHostingEnvironment 变量。

【问题讨论】:

你对你的 Service Fabric 应用做了什么来设置环境变量?您是否按照此处所述进行SetupEntryPoint? azure.microsoft.com/en-us/documentation/articles/… 我正在使用 Visual Studio 中提供的 Service Fabric 模板。它正确地在 ServiceManifest 中预配置了服务条目 xml。我在launchsettings中指定了环境变量 【参考方案1】:

我遇到了同样的问题,并且能够创建一个适合我的解决方案。

如果您查看您的 ASP.NET Core 项目,您应该会看到一个 Program.cs 文件。在它的底部你应该看到以下接口实现:

Task<string> ICommunicationListener.OpenAsync(CancellationToken cancellationToken)

...

您将首先要将其更改为以下内容:

Task<string> ICommunicationListener.OpenAsync(CancellationToken cancellationToken)

    var context = FabricRuntime.GetActivationContext();
    var endpoint = context.GetEndpoint(_endpointName);
    var config = context.GetConfigurationPackageObject("Config");
    var environment = config.Settings.Sections["Environment"].Parameters["ASPNETCORE_ENVIRONMENT"].Value;

    var serverUrl = $"endpoint.Protocol://FabricRuntime.GetNodeContext().IPAddressOrFQDN:endpoint.Port";

    _webHost = new WebHostBuilder().UseKestrel()
                                   .UseContentRoot(Directory.GetCurrentDirectory())
                                   .UseStartup<Startup>()
                                   .UseEnvironment(environment)
                                   .UseUrls(serverUrl)
                                   .Build();

    _webHost.Start();

    return Task.FromResult(serverUrl);

关键部分是.UseEnvironment(environment) 调用,以及从配置中检索环境的支持。这将为 ASP.NET Core 提供选择环境所需的必要信息。

完成此操作后,您显然需要将 ASPNETCORE_ENVIRONMENT 设置添加到配置部分。如下所示:

在您的 ASP.NET Core 项目下,您会找到一个名为 PackageRoot/Config 的目录。其中应该有一个 Settings.xml 文件。在&lt;Settings&gt;标签内添加如下代码...

<Section Name="Environment">
  <Parameter Name="ASPNETCORE_ENVIRONMENT" Value="" />
</Section>

接下来,您将要查看实际 Service Fabric 项目 中的 ApplicationPackageRoot/ApplicationManifest.xml 文件(这不是 ASP.NET Core项目)。需要更改两个文件。

    在文件顶部的&lt;Parameters&gt; 标记内添加 ASPNETCORE_ENVIRONMENT 参数,如下所示:

    <Parameter Name="ASPNETCORE_ENVIRONMENT" DefaultValue="" />
    

    修改您的 &lt;ServiceManifestImport&gt; 标记以包含 &lt;ConfigOverrides&gt; 部分,如下所示:

    <ConfigOverrides>
      <ConfigOverride Name="Config">
        <Settings>
          <Section Name="Environment">
            <Parameter Name="ASPNETCORE_ENVIRONMENT" Value="[ASPNETCORE_ENVIRONMENT]" />
          </Section>
        </Settings>
      </ConfigOverride>
    </ConfigOverrides>
    

最后,修改你的 ApplicationParameters/Local.1Node.xml 和朋友以包含ASPNETCORE_ENVIRONMENT 参数:

<Parameter Name="ASPNETCORE_ENVIRONMENT" Value="Development" />

添加一个可以检索的异常变量需要很多步骤,但它确实为您提供了很大的灵活性,并遵循标准的 Service Fabric 模式来简化部署。我希望这会有所帮助!

【讨论】:

感谢您的详细回答。看起来您所描述的是一般如何在 Service Fabric 中添加设置。这样做会起作用,但是当您右键单击 asp.net 核心项目的项目属性并在属性窗口中更改环境的值时会断开连接。 @TheMuffinMan 没错,确实存在断开连接。如果我在输入此内容后忘记了,请原谅我,但在 Service Fabric 中运行时,项目属性路径根本不起作用,是吗?也许我疯了。 :)【参考方案2】:

answer from Duncan 对我有用,但对我来说有一个小的变化,可能是由于我使用的 ASP.NET Core 和 Service Fabric 的版本。

我需要在我的 Web 无状态服务中覆盖方法 CreateServiceInstanceListeners。 所以这意味着我会有这个代码:

protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()

    return new ServiceInstanceListener[]
    
        new ServiceInstanceListener(serviceContext =>
            new WebListenerCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) =>
            
                ServiceEventSource.Current.ServiceMessage(serviceContext, $"Starting WebListener on url");

                var environment = FabricRuntime.GetActivationContext()
                    ?.GetConfigurationPackageObject("Config")
                    ?.Settings.Sections["Environment"]
                    ?.Parameters["ASPNETCORE_ENVIRONMENT"]?.Value;

                return new WebHostBuilder().UseWebListener()
                    .ConfigureServices(
                        services => services
                            .AddSingleton<StatelessServiceContext>(serviceContext))
                    .UseContentRoot(Directory.GetCurrentDirectory())
                    .UseStartup<Startup>()
                    .UseEnvironment(environment)
                    .UseApplicationInsights()
                    .UseUrls(url)
                    .Build();
            ))
    ;

当然,您需要按照 Duncan 的说明设置 ASPNETCORE_ENVIRONMENT 变量。

【讨论】:

【参考方案3】:

此答案的参考:https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-manage-multiple-environment-app-configuration

我在使用默认模板时遇到了同样的问题。以下与 Duncan 的回答类似,但有两个重要区别:1)您不必更改服务中的任何模板代码,2)IHostingEnvironment 将正确设置。

首先,将ASPNETCORE_ENVIRONMENT变量添加到应用服务的PackageRoot\ServiceManifest.xml文件的&lt;CodePackage&gt;元素中:

<CodePackage Name="Code" Version="1.0.0">
  <EntryPoint>
    <ExeHost>
      <Program>MyService.exe</Program>
      <WorkingFolder>CodePackage</WorkingFolder>
    </ExeHost>
  </EntryPoint>
  <EnvironmentVariables>
    <EnvironmentVariable Name="ASPNETCORE_ENVIRONMENT" Value=""/>
  </EnvironmentVariables>
</CodePackage>

在 Duncan 的回复中,您将对 Service Fabric 应用程序项目的 ApplicationManifest.xml 进行两项更改。首先,设置一个参数(变量),以便在根据您部署项目的方式替换 ApplicationParameters 文件时对其进行修改。然后,将EnvironmentalOverrides 部分添加到您的ServiceManifestImport 元素。两次添加的结果将如下所示:

<Parameters>
  <Parameter Name="MyService_InstanceCount" DefaultValue="-1" />
  <Parameter Name="AspNetCoreEnvironment" DefaultValue="" />
</Parameters>

<ServiceManifestImport>
  <ServiceManifestRef ServiceManifestName="MyServicePkg" ServiceManifestVersion="1.0.0" />
  <EnvironmentOverrides CodePackageRef="Code">
    <EnvironmentVariable Name="ASPNETCORE_ENVIRONMENT" Value="[AspNetCoreEnvironment]" />
  </EnvironmentOverrides>
</ServiceManifestImport>

最后,您可以在各个 ApplicationParameters 文件中添加适当的值:

<Parameters>
  <Parameter Name="MyService_InstanceCount" Value="-1" />
  <Parameter Name="AspNetCoreEnvironment" Value="Development" />
</Parameters>

此时,您可以从服务的属性 - 调试环境变量中删除该变量。

【讨论】:

由于 EnvironmentVariables 是 Service Fabric 中的新功能,我认为这是最优雅的解决方案。

以上是关于通过 Service Fabric 项目进行调试时未使用环境变量的主要内容,如果未能解决你的问题,请参考以下文章

Service Fabric 群集部署失败

Visual Studio 调试器不会自动附加到本地 Service Fabric 服务

如何对 Service Fabric 应用程序进行版本化和分离?

通过Service Fabric应用项目设置的应用环境在哪里可用? Dockerfile 还是 Docker 容器?

Azure Service Fabric v单片

为 Service Fabric 配置 Azure 部署