如何5分钟读懂 Slf4j + Logback 启动流程源码
大家好,我是摸鱼总工,懒惰是程序员的美德,摸鱼才能成为总工。
今天给大家介绍一下,我是如何 5 分钟读懂 Slf4j 启动流程的。
第一步 用 AI 写一个简单的Demo
让大模型写个完整的软件差点意思,但是写个Demo是最擅长不过了。
这一步比较简单,也不是本文的重点,这里就简单描述一下,引入下述依赖:
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.13</version>
</dependency>
然后写个Main方法,就两行代码,跑起来就完事了。
Logger logger = LoggerFactory.getLogger(LoggerRunner.class);
logger.info("This is logger runner");
第一步,耗时最多 1 分钟。但这个过程也很重要,有一个清晰干净的环境,是读代码的重要前提。
第二步 利用 XCodeMap 生成序列图
把程序跑起来实在是太简单了,但是这程序跑起来的背后,都做了些什么呢?总不能翻代码一行行去看吧?
哈哈,不用,XCodeMap 可以帮你一键绘制实时序列图,让你马上拥有上帝视角!
通过 “Run With XCodeMap”,你立即可以得到一张下面这样的图,它是通过采集程序内部的运行时数据生成的,你可以把它理解为程序的 X 光图。
有了这张图,可以认为你朝着 “ 5 分钟读懂 Slf4j 流程”的成就迈出了一大步。
如果之前逐行 Debug 需要2小时,那你现在估计需要 20 分钟,虽然快了不少,但是还远远不够!
因为,面对错综复杂的程序,你还需要识别出主链路!
第三步 识别主链路
如果你看过一些”高效能人士“之类的职场书籍,书中都会告诉你,达成目标的关键就是要找出关键步骤。
读代码也一样!
那我们如何找出代码的关键链路呢?这个话题比较复杂,值得专门写一篇文章来阐述。
但”二八法则“告诉我们,一般都有一些简单的杀手锏可以解决 80% 的问题。
没错,这个方法被我找到了!
那就是,直接根据耗时进行筛选!如果A函数的耗时是100ms,它调用了 B C D 函数,其中B函数消耗了90ms,那我们根本不必去做太多业务语义分析,直觉就可以断定 B 函数是关键链路。
真的是这样吗,我们可以试一下,筛选出 “costMs > 100”的函数,效果图如下。
是不是非常清晰了!
如果熟练运用 XCodeMap,这第二步和第三步,加起来最多1分钟。
我们还剩 3 分钟。
第四步 目标减负
关键函数都找出了,总共也就10个函数左右,在这些函数处打上断点,稍微花点时间,我相信你肯定是可以搞明白整个流程的。但你想在3分钟内,就搞明白,还是很有挑战!
XCodeMap 可以帮我们代码减负,但要达成“5分钟读懂Slf4j启动流程”的成就,还需要目标减负。
我们读代码,到底读的是啥呢?
首先当然是为了解决开发问题。
我们在工作中大量使用开源组件,这些开源组件大部分也都是质量较高的,也就是说,严重的 Bug 一般不太常见。那是不是意味着,我们使用起来就没有问题了呢?非也,问题大大的多!
其中,至少有一半的问题,跟配置和输入有关。
这不难理解,程序本质可以理解为一个“输入输出”的过程,就算程序本身质量极高,那也得是正确的输入,才能得到正确的输出。
说了这么多,落实到本文,我们的程序还有一个配置文件,那就是 logback.xml,通常放在src/main/resources下面。很显然,这个配置文件,是给日志组件的输入,也是唯一的输入,我们理解启动流程的最关键步骤,自然也是要搞明白以下问题:
- 这个配置文件是在哪里加载的?
- 怎么加载的?
- 有哪些加载方式?
- 优先级如何?
带着这个目标,我们再扫一下上面的程序图,你会发现,最关键的函数就是autoConfig
花个1分钟,扫描下这个函数的源码,可以发现 findURLOfDefaultConfigurationFile:
这个函数就是,整个启动流程之关键的关键!
这个函数其实很简单,稍微阅读下,就可以搞明白以下问题:
- 先看,有没有“-Dlogback.configurationFile” 的配置,如果有,从这里加载配置文件
- 再看,classpath下有无 logback-test.xml
- 最后看,classpath下有无 logback.xml
到这里,整个流程其实已经大致清楚。有这个基础知识,如果再出现离奇的日志不生效问题,就可以轻松搞定啦。
后记
为什么突然开始读日志启动源码呢?还是源于一个线上问题啊。
最近项目中,因为不小心升级了 Slf4j 版本,日志配置全部失效,导致日志全部以 debug 级别打印到 nohup.out,把线上硬盘打爆了。后通过排查发现,Slf4j 在 2.x 之后的 bind 方式出现了变化,需要升级对应 logback 的版本。于是,乘着这个契机,把这些源码梳理了一下。
本文讲述的是 slf4j 1.7.32 + logback 1.2.13 的启动流程,有兴趣的同学,可以试试挑战 “5 分钟读懂 slf4j 2.x 的启动流程” 哈!我相信你可以的。
参考:
转载自:https://juejin.cn/post/7375928754146672667