SpringBoot2.7 霸王硬上弓 Logback1.3 → 不甜但解渴

打印 上一主题 下一主题

主题 916|帖子 916|积分 2748

开心一刻

一大早,她就发消息诘责我
她:你给我老实交代,昨晚去哪鬼混了?
我:没有,就哥几个喝了点酒
她:那我给你打了那么多视频,为什么不接?
我:不太方便呀
她:我不信,和你哥们儿喝酒有啥不方便接视频的?
她:你肯定有别的女人了!
我:你老公就坐在我旁边,我敢接?
前情回顾

SpringBoot2.7照旧任性的,就是不支持Logback1.3,你能奈他何 讲了许多,总结下来就两点

  • SpringBoot 2.7.x 默认依靠 Logback 1.2.x,不支持 Logback 1.3.x
    如果强行将 Logback 升级到 1.3.x,启动会报异常
    1. Exception in thread "main" java.lang.NoClassDefFoundError: org/slf4j/impl/StaticLoggerBinder
    2.         at org.springframework.boot.logging.logback.LogbackLoggingSystem.getLoggerContext(LogbackLoggingSystem.java:304)
    3.         at org.springframework.boot.logging.logback.LogbackLoggingSystem.beforeInitialize(LogbackLoggingSystem.java:118)
    4.         at org.springframework.boot.context.logging.LoggingApplicationListener.onApplicationStartingEvent(LoggingApplicationListener.java:238)
    5.         at org.springframework.boot.context.logging.LoggingApplicationListener.onApplicationEvent(LoggingApplicationListener.java:220)
    6.         at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:178)
    7.         at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:171)
    8.         at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:145)
    9.         at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:133)
    10.         at org.springframework.boot.context.event.EventPublishingRunListener.starting(EventPublishingRunListener.java:79)
    11.         at org.springframework.boot.SpringApplicationRunListeners.lambda$starting$0(SpringApplicationRunListeners.java:56)
    12.         at java.util.ArrayList.forEach(ArrayList.java:1249)
    13.         at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:120)
    14.         at org.springframework.boot.SpringApplicationRunListeners.starting(SpringApplicationRunListeners.java:56)
    15.         at org.springframework.boot.SpringApplication.run(SpringApplication.java:299)
    16.         at org.springframework.boot.SpringApplication.run(SpringApplication.java:1300)
    17.         at org.springframework.boot.SpringApplication.run(SpringApplication.java:1289)
    18.         at com.qsl.Application.main(Application.java:15)
    19. Caused by: java.lang.ClassNotFoundException: org.slf4j.impl.StaticLoggerBinder
    20.         at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
    21.         at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    22.         at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
    23.         at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    24.         ... 17 more
    复制代码
    原因也分析过了
    spring-boot-2.7.18 依靠 org.slf4j.impl.StaticLoggerBinder,而 logback 1.3.x 没有该类

  • SpringBoot 2.7.x 支持 Logback 1.3.x 也不是没办法,但有一些限制,同时也存在一些未知的风险
    关于未知的风险,相信大家都能理解,为什么了,这就好比从 JDK8 升级到 JDK 11,你们为什么不敢升,一个道理,因为大版本的升级,变更点往往比较多,乃至会移除掉低版本的一些内容,编译期报错还算直观的(我们可以根据报错调整代码),如果是运行期报错那就头疼了,上了生产就算事故了,这锅你敢背吗?
    所以大版本的升级,意味着我们不但要修复编译期的错,还要进行全方位的测试,尽可能的覆盖所有场景,以排除运行期可能存在的任何异常。业务简朴还好,如果业务非常庞大,这个全量测试是要花大量时间的,不仅开辟会口吐芬芳,测试也会 mmp
    Upgrade to SLF4J 2.0 and Logback 1.4 进行了一些讨论,wilkinsona(Spring Boot 目前 Contributor 榜一)就提到了一些风险点
    内里讨论了许多,Logback 的 Contributor 榜一大哥 ceki 也在内里进行了许多说明与答疑,感兴趣的可以具体看看
    总之就是:通过调整配置,SpringBoot 2.7.x 可以支持 Logback 1.3.x,但风险必要我们自己承担
换个角度想想,我们应该是能理解 Spring Boot 官方的

  • 对 Logback 不是那么熟,只能通过 Logback 官方说明知道变更点(能包管事无巨细列全了?),若变更点太多,不可能每个点都去核实
  • Spring Boot 那么庞大,集成了那么多功能,怕是榜一大哥也不能熟记所有细节(我们敢包管对我们负责的项目标所有细节都了如指掌吗),所以也没法评估升级到 Logback 1.3.x 会有哪些点受影响
所以求稳,Spring Boot 2.x.x 不打算集成 Logback 1.3.x
但是,如果我们也任性一回,非要强扭这个瓜,Spring Boot 是不是也不能奈我们何?
霸王硬上弓

参考这个,我们来配置下

  • 关闭 Spring Boot 的 LoggingSystem
    1. @SpringBootApplication
    2. public class Application {
    3.     public static void main(String[] args) {
    4.         System.setProperty("org.springframework.boot.logging.LoggingSystem", "none");
    5.         SpringApplication.run(Application.class, args);
    6.     }
    7. }
    复制代码
  • 配置文件用 logback.xml
    1. <?xml version="1.0" encoding="UTF-8"?>
    2. <configuration>
    3.     <property name="LOG_FILE" value="/logs/spring-boot-2_7_18.log"/>
    4.     <property name="FILE_LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS}|%level|%t|%line|%-40.40logger{39}:%msg%n"/>
    5.    
    6.     <appender name="FILE" >
    7.         <encoder >
    8.             <pattern>${FILE_LOG_PATTERN}</pattern>
    9.         </encoder>
    10.         <file>${LOG_FILE}</file>
    11.         <rollingPolicy >
    12.             <fileNamePattern>${LOG_FILE}.%d{yyyy-MM-dd}.zip</fileNamePattern>
    13.             <maxHistory>30</maxHistory>
    14.         </rollingPolicy>
    15.     </appender>
    16.    
    17.     <appender name="STDOUT" >
    18.         <encoder>
    19.             <pattern>${FILE_LOG_PATTERN}}</pattern>
    20.         </encoder>
    21.     </appender>
    22.     <root level="${loglevel:-INFO}">
    23.         <appender-ref ref="STDOUT" />
    24.         <appender-ref ref="FILE" />
    25.     </root>
    26. </configuration>
    复制代码
启动确实正常了,我们加点简朴的业务日志,发现日志也输出正常
  1. 2024-07-26 16:46:48.609|INFO|http-nio-8080-exec-1|525|o.s.web.servlet.DispatcherServlet       :Initializing Servlet 'dispatcherServlet'
  2. 2024-07-26 16:46:48.610|INFO|http-nio-8080-exec-1|547|o.s.web.servlet.DispatcherServlet       :Completed initialization in 0 ms
  3. 2024-07-26 16:46:48.632|INFO|http-nio-8080-exec-1|23|com.qsl.web.TestWeb                     :hello接口入参:青石路
  4. 2024-07-26 16:46:50.033|INFO|http-nio-8080-exec-3|23|com.qsl.web.TestWeb                     :hello接口入参:青石路
  5. 2024-07-26 16:46:50.612|INFO|http-nio-8080-exec-4|23|com.qsl.web.TestWeb                     :hello接口入参:青石路
  6. 2024-07-26 16:46:51.150|INFO|http-nio-8080-exec-5|23|com.qsl.web.TestWeb                     :hello接口入参:青石路
  7. 2024-07-26 16:46:51.698|INFO|http-nio-8080-exec-6|23|com.qsl.web.TestWeb                     :hello接口入参:青石路
  8. 2024-07-26 16:46:52.203|INFO|http-nio-8080-exec-7|23|com.qsl.web.TestWeb                     :hello接口入参:青石路
复制代码
日志文件写入也正常
这不仅解渴,还很甜呀
但不要甜的太早,这仅仅只是一个 demo:spring-boot-2_7_18,没有业务代码,简朴的不能再简朴了,你们要是以此来判断甜与不甜,那就大错特错了;应用到项目中,不但要包管可以或许正常启动,还要包管已有的所有业务可以或许正常运行,至于筹划中的业务,那就将来再说,谁知道明天和意外哪个先来,认真过好当下!
初步实验,是可行的,所以你们大胆的去试吧,但要做好全方位的业务测试
wilkinsona 提到了,关闭 Spring Boot 的 LoggingSystem 后,用的是 Logback 的默认配置,配置文件必须是 logback.xml 而不能是 logback-spring.xml;固然榜一大哥的话很权威,但我们主打一个任性,就想来试试 logback-spring.xml,会有什么样的结果,直接将 logback.xml 改名成 logback-spring.xml,能启动起来,但有一堆 debug 日志,重点是
日志没有写入文件
wilkinsona 诚不欺我!
原理分析

关闭了 Spring Boot 的 LoggingSystem 后,日志相关的全权交给 Logback,而关于 Logback 的配置文件加载,我是写过一篇详解的:从源码来理解slf4j的绑定,以及logback对配置文件的加载,直接跳到总结部分,有这么一段
编译期间,完成slf4j的绑定以及logback配置文件的加载。slf4j会在classpath中寻找org/slf4j/impl/StaticLoggerBinder.class(会在具体的日志框架如log4j、logback等中存在),找到并完成绑定;同时,logback也会在classpath中寻找配置文件,先找logback.configurationFile、没有则找logback.groovy,若logback.groovy也没有,则找logback-test.xml,若logback-test.xml照旧没有,则找logback.xml,若连logback.xml也没有,那么说明没有配置logback的配置文件,那么logback则会启用默认的配置(日志信息只会打印在控制台)
虽说 Logback 是 1.1.17,而不是 1.3.14,但对配置文件的加载应该是没变的
大家注意看我的措辞:应该,这样纵然变了,你们也不能说我,因为我说的是应该
保险起见,你们应该去看下 1.3.14 的源码!
这也是为什么配置文件是 logback.xml 的时间,日志能正常写入文件,而是 logback-spring.xml 时间,日志不能写入日志文件的原因,因为 Logback 不认 logback-spring.xml,Spring Boot 才认!
至于 Spring Boot LoggingSystem 嘛,等我掌握了再来和你们聊,一定要等我哟
总结

Spring Boot 2.x.x 默认依靠 Logback 1.2.x,不支持 Logback 1.3.x,但是通过设置
System.setProperty("org.springframework.boot.logging.LoggingSystem", "none");
启动时不报错的,再结合 logback.xml,日志是可以或许正常写入日志文件的;但是保险起见,照旧不保举升级到 Logback 1.3.x
能不动就不要动,改好没绩效,改出问题要背锅,吃力不讨好,又不是不能跑
如果一定要升级,那就做好全量测试,把所有业务场景都覆盖到

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

我可以不吃啊

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表