程序在发布部署时候,设置环境ASPNETCORE_URLS
不生效,也没在代码里使用UseUrls("xxxx")
,启动一直是http://localhost:5000
.最后测试发现只有在appsettings.json
中配置urls
才生效,网上找了半天资料也没看到有什么问题。html
最终翻看源代码,发现是在StartUp
中的Configure
替换了全局IConfiguration
致使。linux
平时开发大致知道程序启动时候端口启用顺序是
UseUrls("xxx")
> 环境变量 > 默认,具体是怎么肯定使用哪一个配置的,没找到资料,全部才有了本文。git
ASPNETCORE_URLS
#windows set ASPNETCORE_URLS=http://localhost:6000 #linux export ASPNETCORE_URLS=http://localhost:6000
UseUrls("http://localhost:6000")
appsettings.json
新增urls
或者server.urls
配置{ "urls":"http://localhost:6000;http://localhost:6001", "server.urls":"http://localhost:6000;http://localhost:6001" }
程序启动过程当中,一个配置key会重复使用,先放这里github
//WebHostDefaults.ServerUrlsKey以下 public static readonly string ServerUrlsKey = "urls";
今天是介绍启动方式,因此web启动流程不是重点。直接进入正题。web
Web启动最终是调用WebHost.StartAsync
,源代码在这WebHost
。其中有个方法EnsureServer
来获取启动地址json
private static readonly string DeprecatedServerUrlsKey = "server.urls"; //省略 var urls = _config[WebHostDefaults.ServerUrlsKey] ?? _config[DeprecatedServerUrlsKey];
是从全局IConfigration
实例中获取启动地址。因此个人遇到问题这里就解决了。但环境变量和UseUrls
是如何解析并记载进来的呢?下面就开今天讲解。windows
通常Web程序启动代码以下:app
Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); }).Build().Run();
其中ConfigureWebHostDefaults
的会用调用扩展方法ConfigureWebHost
ide
public static IHostBuilder ConfigureWebHostDefaults(this IHostBuilder builder, Action<IWebHostBuilder> configure) { return builder.ConfigureWebHost(webHostBuilder => { WebHost.ConfigureWebDefaults(webHostBuilder); configure(webHostBuilder); }); }
以上代码都是定义在Microsoft.Extensions.Hosting
中。函数
继续看ConfigureWebHost
代码,这个方法就定义在Microsoft.AspNetCore.Hosting
程序集中了。
public static IHostBuilder ConfigureWebHost(this IHostBuilder builder, Action<IWebHostBuilder> configure) { //这里会加载环境变量 var webhostBuilder = new GenericWebHostBuilder(builder); //这里会调用UseUrls等扩展方法 configure(webhostBuilder); builder.ConfigureServices((context, services) => services.AddHostedService<GenericWebHostService>()); return builder; }
在GenericWebHostBuilder
构造函数里有以下代码,用来初始化配置,最终添加到全局
IConfiguration
实例中,也就是Host
中IConfiguration
实例。
builder.ConfigureServices((context, services) => services.AddHostedService
());这个是web启动重点,有兴趣的能够看下
//加入环境变量配置 _config = new ConfigurationBuilder() .AddEnvironmentVariables(prefix: "ASPNETCORE_") .Build(); //把配置加载到Host _builder.ConfigureHostConfiguration(config => { config.AddConfiguration(_config); // We do this super early but still late enough that we can process the configuration // wired up by calls to UseSetting ExecuteHostingStartups(); })
AddEnvironmentVariables
环境变量解析最终会使用EnvironmentVariablesConfigurationProvider
,有兴趣的能够看下AddEnvironmentVariables
源代码,EnvironmentVariablesConfigurationProvider
解析环境的方法以下。
public override void Load() { Load(Environment.GetEnvironmentVariables()); } internal void Load(IDictionary envVariables) { var data = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); //这里是筛选ASPNETCORE_开头的环境变量 var filteredEnvVariables = envVariables .Cast<DictionaryEntry>() .SelectMany(AzureEnvToAppEnv) .Where(entry => ((string)entry.Key).StartsWith(_prefix, StringComparison.OrdinalIgnoreCase)); foreach (var envVariable in filteredEnvVariables) { //这里会把前缀去掉加到配置里 var key = ((string)envVariable.Key).Substring(_prefix.Length); data[key] = (string)envVariable.Value; } Data = data; }
IConfiguration
中的key是不区分大小写的,全部最终的效是在全局IConfiguration
中新增一条key为urls的记录。
而若是使用默认Host.CreateDefaultBuilder()
,appsettings.json
中的配置会先加载。
若是在appsettings.json中配置urls
的话,环境变量也定义了,就会被环境变量的覆盖掉。
UseUrls解析
最终会调用GenericWebHostBuilder
中的UseSetting
//UseUrls代码以下 public static IWebHostBuilder UseUrls(this IWebHostBuilder hostBuilder, params string[] urls) { if (urls == null) { throw new ArgumentNullException(nameof(urls)); } return hostBuilder.UseSetting(WebHostDefaults.ServerUrlsKey, string.Join(ServerUrlsSeparator, urls)); } //GenericWebHostBuilder中的UseSetting public IWebHostBuilder UseSetting(string key, string value) { _config[key] = value; return this; }
因为这个方法是在 new GenericWebHostBuilder(builder);
以后调用,就是 configure(webhostBuilder);
,上面代码也有说明。因此IConfiguration
中urls若是有值,又会被覆盖掉。因此优先级最高的是UseUrls()
。
假如以上3种配置都没有,就是地址为空,会使用默认策略。这里是源代码,下面是默认策略使用的地址
/// <summary> /// The endpoint Kestrel will bind to if nothing else is specified. /// </summary> public static readonly string DefaultServerAddress = "http://localhost:5000"; /// <summary> /// The endpoint Kestrel will bind to if nothing else is specified and a default certificate is available. /// </summary> public static readonly string DefaultServerHttpsAddress = "https://localhost:5001";
UseUrls("xxxx")
> 环境变量 > appsetting.json
配置urls
>默认地址IConfiguration
,若是不手动加入环境变量解析的话,会丢失一部分配置数据。做者:cgyqu
出处:http://www.javashuo.com/article/p-kqlxcvup-da.html 本站使用「署名 4.0 国际」创做共享协议,转载请在文章明显位置注明做者及出处。