背景
程式在發布部署時候,設定環境ASPNETCORE_URLS不生效,也沒在代碼里使用UseUrls("xxxx"),啟動一直是http://localhost:5000.最后測驗發現只有在appsettings.json中配置urls才生效,網上找了半天資料也沒看到有什么問題,
最終翻看源代碼,發現是在StartUp中的Configure替換了全域IConfiguration導致,
平時開發大體知道程式啟動時候埠啟用順序是
UseUrls("xxx")> 環境變數 > 默認,具體是怎么確定使用哪個配置的,沒找到資料,所有才有了本文,
啟動地址配置的幾種方式介紹
- 環境變數
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會重復使用,先放這里
//WebHostDefaults.ServerUrlsKey如下
public static readonly string ServerUrlsKey = "urls";
Web專案啟動地址配置說明
今天是介紹啟動方式,所以web啟動流程不是重點,直接進入正題,
Web啟動最終是呼叫WebHost.StartAsync,源代碼在這WebHost,其中有個方法EnsureServer來獲取啟動地址
private static readonly string DeprecatedServerUrlsKey = "server.urls";
//省略
var urls = _config[WebHostDefaults.ServerUrlsKey] ?? _config[DeprecatedServerUrlsKey];
是從全域IConfigration實體中獲取啟動地址,所以我的遇到問題這里就解決了,但環境變數和UseUrls是如何決議并記載進來的呢?下面就開今天講解,
環境變數配置詳解
一般Web程式啟動代碼如下:
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
}).Build().Run();
其中ConfigureWebHostDefaults的會用呼叫擴展方法ConfigureWebHost
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 = https://www.cnblogs.com/cgyqu/p/new Dictionary(StringComparer.OrdinalIgnoreCase);
//這里是篩選ASPNETCORE_開頭的環境變數
var filteredEnvVariables = envVariables
.Cast()
.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決議
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,如果不手動加入環境變數決議的話,會丟失一部分配置資料, - 將自己的配置注入的全域,可以使用以下方式,這樣就會把配置追加到全域的
IConfiguration中
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(builder =>
{
builder.UseStartup<Startup>();
}).ConfigureAppConfiguration(config =>
{
config.AddJsonFile("config.json", true, true);
}).Build().Run();
作者:cgyqu 出處:https://www.cnblogs.com/cgyqu/p/12169014.html 本站使用「署名 4.0 國際」創作共享協議,轉載請在文章明顯位置注明作者及出處,
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/73238.html
標籤:.NET Core
