通过 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 文件。在<Settings>
标签内添加如下代码...
<Section Name="Environment">
<Parameter Name="ASPNETCORE_ENVIRONMENT" Value="" />
</Section>
接下来,您将要查看实际 Service Fabric 项目 中的 ApplicationPackageRoot/ApplicationManifest.xml 文件(这不是 ASP.NET Core项目)。需要更改两个文件。
在文件顶部的<Parameters>
标记内添加 ASPNETCORE_ENVIRONMENT 参数,如下所示:
<Parameter Name="ASPNETCORE_ENVIRONMENT" DefaultValue="" />
修改您的 <ServiceManifestImport>
标记以包含 <ConfigOverrides>
部分,如下所示:
<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
文件的<CodePackage>
元素中:
<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 项目进行调试时未使用环境变量的主要内容,如果未能解决你的问题,请参考以下文章
Visual Studio 调试器不会自动附加到本地 Service Fabric 服务
如何对 Service Fabric 应用程序进行版本化和分离?