zoukankan      html  css  js  c++  java
  • ASP.Net Core配置文件问题 -- 环境变量

      最近排查一个ASP.Net Core项目的Bug,用LogInformation()记录一些运行日志,本地测试日志记录正常,然后发到RC环境测试,结果发现死活没有日志信息。


      首先想到就是LogLevel设置有问题。检查了基础的配置文件(appsettings.json)没有问题,而RC环境的配置文件(appsettings.RC.json)未配置Logging节点,也就不会覆盖。

     1 "Logging": {
     2   "IncludeScopes": false,
     3   "LogLevel": {
     4     "Default": "Information",
     5     "System": "Warning",
     6     "Microsoft": "Warning"
     7   },
     8   "Console": {
     9     "LogLevel": {
    10       "Default": "Warning"
    11     }
    12   }
    13 }
    appsettings.json

      然后检查了涉及appsettings.json的代码。在Startup.cs中,会根据“environment.json”文件中配置的“EnvironmentName”值,来加载不同配置文件。

     1 private readonly ILoggerFactory m_LoggerFactory;
     2 private readonly IConfiguration m_Configuration;
     3 
     4 public Startup(IHostingEnvironment env, ILoggerFactory loggerFactory)
     5 {
     6     m_LoggerFactory = loggerFactory;
     7 
     8     var environmentName = GetEnvironmentName();
     9     var builder = new ConfigurationBuilder()
    10         .SetBasePath(env.ContentRootPath)
    11         .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
    12         .AddJsonFile($"appsettings.{environmentName}.json", optional: true, reloadOnChange: true);
    13 
    14     m_Configuration = builder.Build();
    15 }
    16 
    17 private static string GetEnvironmentName()
    18 {
    19     var configuration = new ConfigurationBuilder()
    20         .AddJsonFile("environment.json", optional: true)
    21         .Build();
    22     return configuration["EnvironmentName"] ?? string.Empty;
    23 }
    Startup

       可是environment.json配置也没问题,而其中的m_Configuration变量只是会注入IoC中供业务代码读取配置使用,并没有对Logging配置做任何修改。

      之后又想到,所有环境的配置文件都是放在同一个目录下,是否是串文件了呢?而其中appsettings.Production.json中确实有配置Logging.LogLevel为“Warning”,如果加载了这个配置,那LogInformation()就不会输出日志了。因而调整了下appsettings.Production.json中的Loggind.LogLevel为“Information”,然后再测试,嘿,有日记信息了!也就是说,Production的配置文件确实被加载了。

      再次检查代码发现并未有明确加载Production文件,那该不会是某个系统方法通过环境变量ASPNETCORE_ENVIRONMENT加载的吧?因为未设置该值(确实没设置)默认就会是Production[1]

     

      于是立马修改ASPNETCORE_ENVIRONMENT=RC(注意是1个“_”),还原appsettings.Production.json,然后重启服务测试,不出所料,日志正常记录。那么,接下来就是找到那个“系统方法”了。

      仔细翻了翻官方文档,找到了以下内容[2]

      CreateDefaultBuilder方法(2.0新增[4])会调用2次AddJsonFile(),第1次加载appsettings.json,第2次加载appsettings.{Environment}.json,而Environment取至IHostingEnvironment.EnvironmentName,即环境值。对应源码[5]

     1 builder.UseKestrel((builderContext, options) =>
     2 {
     3     options.Configure(builderContext.Configuration.GetSection("Kestrel"));
     4 })
     5 .ConfigureAppConfiguration((hostingContext, config) =>
     6 {
     7     var env = hostingContext.HostingEnvironment;
     8 
     9     config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
    10           .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
    11 
    12     if (env.IsDevelopment())
    13     {
    14         var appAssembly = Assembly.Load(new AssemblyName(env.ApplicationName));
    15         if (appAssembly != null)
    16         {
    17             config.AddUserSecrets(appAssembly, optional: true);
    18         }
    19     }
    20 
    21     config.AddEnvironmentVariables();
    22 
    23     if (args != null)
    24     {
    25         config.AddCommandLine(args);
    26     }
    27 })
    CreateDefaultBuilder

      好嘛,真相大白:

    1. 未设置环境变量ASPNETCORE_ENVIRONMENT,则默认为Production
    2. 调用CreateDefaultBuilder方法构建WebHost,自动加载appsettings.Production.json
    3. 最终,Logging.LogLevel被设置为了Production配置的值“Warning”,因而LogInformation()失效

      那么,只要正确设置ASPNETCORE_ENVIRONMENT值即可解决问题咯。

      但是,还记得上面提到的“environment.json”文件吗?这个文件目的本就是为了方便切换不同环境的配置文件而建立的,Logging的配置理应由它来决定,如果通过ASPNETCORE_ENVIRONMENT来设置,就多此一举了。那怎么才能让在Startup构造方法中构建的m_Configuration对象对Logging生效呢?官方也给出了方案:ConfigureAppConfiguration方法[2]!是不是觉得眼熟?在上面的CreateDefaultBuilder方法中正是通过ConfigureAppConfiguration()来加载默认配置的。

      最终,代码修正如下: 

     1 private static IWebHost BuildWebHost(string[] args)
     2 {
     3     return WebHost.CreateDefaultBuilder(args)
     4         .CaptureStartupErrors(true)
     5         .UseSetting(WebHostDefaults.DetailedErrorsKey, "true")
     6         .ConfigureAppConfiguration((hostingContext, config) =>
     7         {
     8             config.Sources.Clear();
     9             config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
    10                 .AddJsonFile($"appsettings.{GetEnvironmentName()}.json", optional: true, reloadOnChange: true);
    11         })
    12         .UseStartup<Startup>()
    13         .UseNLog()
    14         .Build();
    15 }
    16 
    17 private static string GetEnvironmentName()
    18 {
    19     var configuration = new ConfigurationBuilder()
    20         .AddJsonFile("environment.json", optional: true)
    21         .Build();
    22     return configuration["EnvironmentName"] ?? string.Empty;
    23 }
    BuildWebHost

       构建m_Configuration的代码,由Startup.cs转移到了Program.cs,而在Startup.cs中,Configuration对象可直接注入:

    1 private readonly ILoggerFactory m_LoggerFactory;
    2 private readonly IConfiguration m_Configuration;
    3 
    4 public Startup(IConfiguration configuration, ILoggerFactory loggerFactory)
    5 {
    6     m_LoggerFactory = loggerFactory;
    7     m_Configuration = configuration;
    8 }
    Startup

      至此,告一段落!

      参考文档

    1. 官方文档:配置Environment
    2. 官方文档:配置Configuration
    3. 官方文档:配置Logging
    4. ASP.Net Core 1.x迁移至2.0
    5. CreateDefaultBuilder源码
    6. asp.netcore 深入了解配置文件加载过程
  • 相关阅读:
    Set和Map
    将博客搬至CSDN
    (转)VS制作安装包
    C#俄罗斯方块实现思路及源码
    ASP.NET网站部署过程
    2016百度之星资格赛总结
    数据库编程常见错误总结
    (转)Android 如何全局获取Context
    Android数据文件存储
    关于工程文档中图表的使用
  • 原文地址:https://www.cnblogs.com/linys2333/p/9970597.html
Copyright © 2011-2022 走看看