内容简介:Q 业务系统在做发布前检查工作时,发现一台单机的主日志没有打印,而其他生产机器的日志表现则是正常的。通过 greys 观察主 service 的业务入口,发现该机器线上流量的请求接受、逻辑处理、结果反馈均正常。排查范围就聚焦在 log jar 配置上。
背景
Q 业务系统在做发布前检查工作时,发现一台单机的主日志没有打印,而其他生产机器的日志表现则是正常的。
排查流
思考
通过 greys 观察主 service 的业务入口,发现该机器线上流量的请求接受、逻辑处理、结果反馈均正常。排查范围就聚焦在 log jar 配置上。
解决
- SOF搜索,找到一篇 log 绑定包冲突的排查 & 解决方法。排查本地是否存在绑定包冲突的问题,结果发现确实是的 ——
- 引入 slf4j-log4j12-empty_version.jar,排掉其他 jar 包引入的日志绑定包。
- 发布、部署该单机,问题解决。
原理
研究了一下 slf4j-log4j12 实现绑定的原理——简单来说,日志输出到单机本地,需要以下 3 类 jar 包相互配合:
- slf4j 。业务程序调用的日志接口,只有接口定义,没有实现,从而保证了代码层调用 Log 的统一
- 日志组件。比如 log4j-api、log4j-core,是 log4j2 的内部实现;logback-classic、logback-core,是 logback 的内部实现;log4j,是 logj4 的内部实现。它们本身是没有冲突的,可以并存
- 绑定包。将 slf4j-api 的接口绑定到对应的 log 实现上,比如 slf4j-log4j12、log4j-slf4j-impl(关键)
具体到代码实现上,就是通过 StaticLoggerBinder.getSingleton ( ) 方法返回的单例,实现包的绑定 ——
qjt 程序中,同时存在着两类绑定包:log4j-slf4j-impl-2.7.jar 和 slf4j-log4j12-1.7.2.jar。这实际是一种意义上的日志绑定包冲突 —— 选定哪个包,取决于 ClassLoader 先加载哪个,具有一定的随机性。
- 其他生产机 StaticLoggerBinder 的加载情况 —— 可以看到使用的是 log4j-slf4j-impl-2.7.jar
- 问题单机 StaticLoggerBinder 的加载情况 —— 可以看到使用的是 slf4j-log4j12-1.7.2.jar
核心:slf4j-log4j12 意指 slf4j 底层桥接到 log4j;log4j-slf4j-impl 意指 log4j 底层桥接到 slf4j。通过机器本地 lib 库也可以看到,qjt 用的 facade 是 log4j。所以如果 classloader 先加载了 slf4j-log4j12 的话,就会无法打印日志 —— 因为 log4j 找不到具体的桥接实现了。
再来看一下 slf4j-log4j12-empty_version.jar 是什么东东。通过观察它的包结构,可以看到其实是 slf4j 绑定包的空实现,由此排掉了其他 jar 包引入的 slf4j-log4j12 实现。
小结
叙述到此,可以发现正是 ClassLoader 随机加载两类绑定包的不同,从而导致了日志打印表现的不同。为了避免该情况,强烈建议各位同学排查是否存在绑定包的冲突。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Perl语言编程
[美] Larry Wall、Tom Christiansen、Jon Orwant / 何伟平 / 中国电力出版社 / 2001-12 / 129.00元
这不仅仅是一本关于Perl的书籍,更是一本独一无二的开发者自己介绍该语言及其文化的书籍。Larry Wall是Perl的开发者,他就这种语言的未来发展方向提出了自己的看法。Tom Christiansen是最早的几个拥护者之一,也是少数几个在错综复杂的中游刃有余的人之一。Jon Orwant是《Perl Journal》的主编,该杂志把Perl社区组合成了一个共同的论坛,以进行Perl新的开发。一起来看看 《Perl语言编程》 这本书的介绍吧!