程序在發佈部署時候,設置環境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 國際」創做共享協議,轉載請在文章明顯位置註明做者及出處。