配置SpringBoot-从日志系统配置说起

1,553 阅读2分钟
原文链接: www.guxingke.com

应用可以死, 日志必须活.


大小系统都需要打日志. 系统在不同环境下对日志的配置要求是不一样的 比如 开发本地: 直接输出到控制台 生产环境: 输出到文件或者额外的日志收集系统, 比如 graylog. (本文不探讨具体日志系统的配置)

Spring Boot 官方方案

Profile-specific Configuration

1545102456.png Logback 专属, 各环境配置归于同一文件, 通过 Spring Profile 启用.

  • 优点: 几乎无改动, 只需系统配置文件制定 spring.profiles.action=
  • 缺点: 多环境配置混合在一起, 应用运行时应该对运行配置无感知.

放弃.

配置 logging.config

1545102771.png 需要在配置文件中指定 logging.config 需要提供多个 日志配置文件 e.g logging.config=classpath:logback-console.xml logging.config=classpath:logback-file.xml logging.config=classpath:logback-graylog.xml 可行.

落地

采用 配置 logging.config 方案

背景: 公司配置文件采用基于文件的配置中心, 通过发布系统发布到应用机器指定目录, 应用始终读取指定目录下配置文件.

几个问题

  1. 如何读取指定目录应用配置?
  2. 如何保证日志初始化时能读取到指定的 config ?

官方的外置配置文件加载顺序

1545103791.png 从文档可以看出, 默认的 Spring Boot 应用的配置文件 classpath:application.propreties 是在第 15 顺位上加载的.

Application properties packaged inside your jar (application.properties and YAML variants).

@PropertySource ?

即第 16 顺位的选择. 然而, 事情没有这么简单. 日志系统由于其特殊性, 需要尽可能早的初始化.

Since logging is initialized before the ApplicationContext is created, it is not possible to control logging from @PropertySources in Spring @Configuration files. The only way to change the logging system or disable it entirely is via System properties. 大意就是 logging system 初始化在 ApplicationContext 创建之前, 所以 @PropertySource 这种配置方式是无法影响到日志系统初始化的(毕竟事儿都干完了)

此路不通

Command line arguments ?

顺着配置顺序往上找, 相对来讲 命令行参数 可以成本极低的应用上去. e.g

  public static void main(String[] args) throws UnknownHostException {
    System.out.println(new Date() + "  loaded...");
    args = new String[1];
    args[0] =
      "--spring.config.location=/etc/conf/app/xxx/application.properties";

    ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);
    ConfigurableEnvironment env = context.getEnvironment();

    log.info("\n----------------------------------------------------------\n\t" +
        "Application '{}' is running! Access URLs:\n\t" +
        "Local: \t\thttp://localhost:{}\n\t" +
        "External: \thttp://{}:{}\n\t" +
        "Profile(s): \t{}\n----------------------------------------------------------",
      env.getProperty("spring.application.name"),
      env.getProperty("server.port"),
      InetAddress.getLocalHost().getHostAddress(),
      env.getProperty("server.port"),
      env.getActiveProfiles());

    System.out.println(new Date() + "  started...");
  }

如预期, 日志系统使用了正确的指定配置.

告一段落

问题基本解决, 但并不优雅, hack 命令行参数, 并且存在一定的局限性. 此处暂且搁置.

后记

  • 有没有更优雅的解决此问题的方法?
  • 为何 Spring Boot 的配置文件加载顺序是这般定义?
  • Spring Boot 加载配置是如何实现的?
  • Spring Cloud Config 等配置中心的配置是如何结合到具体应用中的?
  • Spring Cloud Config 等配置中心的配置支持日志系统配置文件位置的配置吗?

...

待后续拆而析之.