AspNetCore 启动地址配置详解
背景
程序在發(fā)布部署時(shí)候,設(shè)置環(huán)境ASPNETCORE_URLS不生效,也沒(méi)在代碼里使用UseUrls("xxxx"),啟動(dòng)一直是http://localhost:5000.最后測(cè)試發(fā)現(xiàn)只有在appsettings.json中配置urls才生效,網(wǎng)上找了半天資料也沒(méi)看到有什么問(wèn)題。
最終翻看源代碼,發(fā)現(xiàn)是在StartUp中的Configure替換了全局IConfiguration導(dǎo)致。
平時(shí)開發(fā)大體知道程序啟動(dòng)時(shí)候端口啟用順序是
UseUrls("xxx")>?環(huán)境變量?> 默認(rèn),具體是怎么確定使用哪個(gè)配置的,沒(méi)找到資料,所有才有了本文。
啟動(dòng)地址配置的幾種方式介紹
環(huán)境變量ASPNETCORE_URLS
UseUrls("http://localhost:6000")
appsettings.json新增urls或者server.urls配置
使用系統(tǒng)默認(rèn)
說(shuō)明
程序啟動(dòng)過(guò)程中,一個(gè)配置key會(huì)重復(fù)使用,先放這里
//WebHostDefaults.ServerUrlsKey如下 public static readonly string ServerUrlsKey = "urls";Web項(xiàng)目啟動(dòng)地址配置說(shuō)明
今天是介紹啟動(dòng)方式,所以web啟動(dòng)流程不是重點(diǎn)。直接進(jìn)入正題。
Web啟動(dòng)最終是調(diào)用WebHost.StartAsync,源代碼在這WebHost。其中有個(gè)方法EnsureServer來(lái)獲取啟動(dòng)地址
private static readonly string DeprecatedServerUrlsKey = "server.urls";//省略 var urls = _config[WebHostDefaults.ServerUrlsKey] ?? _config[DeprecatedServerUrlsKey];是從全局IConfigration實(shí)例中獲取啟動(dòng)地址。所以我的遇到問(wèn)題這里就解決了。但環(huán)境變量和UseUrls是如何解析并記載進(jìn)來(lái)的呢?下面就開今天講解。
環(huán)境變量配置詳解
一般Web程序啟動(dòng)代碼如下:
Host.CreateDefaultBuilder(args).ConfigureWebHostDefaults(webBuilder =>{webBuilder.UseStartup<Startup>();}).Build().Run();其中ConfigureWebHostDefaults的會(huì)用調(diào)用擴(kuò)展方法ConfigureWebHost
public static IHostBuilder ConfigureWebHostDefaults(this IHostBuilder builder, Action<IWebHostBuilder> configure){return builder.ConfigureWebHost(webHostBuilder =>{WebHost.ConfigureWebDefaults(webHostBuilder);configure(webHostBuilder);});}以上代碼都是定義在Microsoft.Extensions.Hosting中。
繼續(xù)看ConfigureWebHost代碼,這個(gè)方法就定義在Microsoft.AspNetCore.Hosting程序集中了。
public static IHostBuilder ConfigureWebHost(this IHostBuilder builder, Action<IWebHostBuilder> configure) {//這里會(huì)加載環(huán)境變量var webhostBuilder = new GenericWebHostBuilder(builder);//這里會(huì)調(diào)用UseUrls等擴(kuò)展方法configure(webhostBuilder);builder.ConfigureServices((context, services) => services.AddHostedService<GenericWebHostService>());return builder; }在GenericWebHostBuilder?構(gòu)造函數(shù)里有如下代碼,用來(lái)初始化配置,最終添加到全局
IConfiguration實(shí)例中,也就是Host中IConfiguration實(shí)例。
builder.ConfigureServices((context, services) => services.AddHostedService());這個(gè)是web啟動(dòng)重點(diǎn),有興趣的可以看下
//加入環(huán)境變量配置 _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 UseSettingExecuteHostingStartups(); })AddEnvironmentVariables環(huán)境變量解析最終會(huì)使用EnvironmentVariablesConfigurationProvider,有興趣的可以看下AddEnvironmentVariables源代碼,EnvironmentVariablesConfigurationProvider解析環(huán)境的方法如下。
public override void Load() {Load(Environment.GetEnvironmentVariables()); }internal void Load(IDictionary envVariables) {var data = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);//這里是篩選ASPNETCORE_開頭的環(huán)境變量var filteredEnvVariables = envVariables.Cast<DictionaryEntry>().SelectMany(AzureEnvToAppEnv).Where(entry => ((string)entry.Key).StartsWith(_prefix, StringComparison.OrdinalIgnoreCase));foreach (var envVariable in filteredEnvVariables){//這里會(huì)把前綴去掉加到配置里var key = ((string)envVariable.Key).Substring(_prefix.Length);data[key] = (string)envVariable.Value;}Data = data; }IConfiguration中的key是不區(qū)分大小寫的,所有最終的效是在全局IConfiguration中新增一條key為urls的記錄。
而如果使用默認(rèn)Host.CreateDefaultBuilder(),appsettings.json中的配置會(huì)先加載。
如果在appsettings.json中配置urls的話,環(huán)境變量也定義了,就會(huì)被環(huán)境變量的覆蓋掉。
UseUrls解析
UseUrls解析最終會(huì)調(diào)用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; }由于這個(gè)方法是在?new GenericWebHostBuilder(builder);
之后調(diào)用,就是?configure(webhostBuilder);,上面代碼也有說(shuō)明。所以IConfiguration中urls如果有值,又會(huì)被覆蓋掉。所以優(yōu)先級(jí)最高的是UseUrls()。
默認(rèn)地址
假如以上3種配置都沒(méi)有,就是地址為空,會(huì)使用默認(rèn)策略。這里是源代碼,下面是默認(rèn)策略使用的地址
/// <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";結(jié)論
啟動(dòng)端口設(shè)置優(yōu)先級(jí)如下:
UseUrls("xxxx")?> 環(huán)境變量 >?appsetting.json配置urls>默認(rèn)地址
不要隨意替換全局的IConfiguration,如果不手動(dòng)加入環(huán)境變量解析的話,會(huì)丟失一部分配置數(shù)據(jù)。
作者:cgyqu
出處:https://www.cnblogs.com/cgyqu/p/12169014.html
總結(jié)
以上是生活随笔為你收集整理的AspNetCore 启动地址配置详解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Excel模板导出之导出教材订购表
- 下一篇: BeetleX网关非法Url请求拦截插件