前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >记一次log4j不打印日志的踩坑记

记一次log4j不打印日志的踩坑记

作者头像
我是攻城师
发布2019-09-25 09:52:15
9.9K0
发布2019-09-25 09:52:15
举报
文章被收录于专栏:我是攻城师我是攻城师

起因

前几天一个跑有java应用的生产集群(200多台物理机)升级了一个版本,重启后发现约有50台机器日志不能正常输出,但其程序却能正常的运行,在生产环境中,日志是非常重要的一个监控手段,如果没有日志输出,无疑是非常危险的。

排查 & 解决

发现这一情况后,立即开始从jdk环境和版本,cpu负载,内存gc,线程stack,死锁,磁盘容量等多方面排查,但均没有发现异常情况,唯一的一点信息是Java进程重启时重定向到out文件里面的控制台输出,如下(以下均为复现时的输出):

代码语言:javascript
复制
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/Users/qindongliang/.m2/repository/org/apache/logging/log4j/log4j-slf4j-impl/2.3/log4j-slf4j-impl-2.3.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/Users/qindongliang/.m2/repository/org/slf4j/slf4j-log4j12/1.7.12/slf4j-log4j12-1.7.12.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [org.apache.logging.slf4j.Log4jLoggerFactory]

起初并没有在意日志包冲突的这个细节,因为其他正常启动并能够正常打印log的机器中,也有同样的输出。所以基本肯定与这个冲突关系不大。

但苦于没有其他日志输出,并且当前的进程是在正常的Runnable状态中,所以又把目光回到了刚才的out文件,经过与正常机器中大部分out文件比较,发现了一点端倪。

(1)大多数能够正常打印log机器的out文件输出是:

代码语言:javascript
复制
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/Users/qindongliang/.m2/repository/org/apache/logging/log4j/log4j-slf4j-impl/2.3/log4j-slf4j-impl-2.3.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/Users/qindongliang/.m2/repository/org/slf4j/slf4j-log4j12/1.7.12/slf4j-log4j12-1.7.12.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [org.apache.logging.slf4j.Log4jLoggerFactory]

(2)少部分正常打印log的机器和其他不打印log的机器的out文件输出是:

代码语言:javascript
复制
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/Users/qindongliang/.m2/repository/org/slf4j/slf4j-log4j12/1.7.12/slf4j-log4j12-1.7.12.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/Users/qindongliang/.m2/repository/org/apache/logging/log4j/log4j-slf4j-impl/2.3/log4j-slf4j-impl-2.3.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [org.slf4j.impl.Log4jLoggerFactory]

对比上面两个输出文件中的第三行,第四行和最后一行,发现不同的机器有可能输出的不一样,另外一点能够得到的是正常的机器sfl4j binding最后一行都是一样的类:

代码语言:javascript
复制
org.apache.logging.slf4j.Log4jLoggerFactory

而少数正常和所有不正常的slf4j binding的类如下:

代码语言:javascript
复制
org.slf4j.impl.Log4jLoggerFactory

这明显是slf4j binding包冲突造成的,经过调查发现,前者是log4j2.x用的工厂实现类,而后者是兼容log4j1.x用的工厂类,他们分别位于:

代码语言:javascript
复制
log4j-slf4j-impl-2.3.jar

代码语言:javascript
复制
slf4j-log4j12-1.7.12.jar

这两个jar包中,都有各自的StaticLoggerBinder类,所以才造成了冲突,因为我们用的是log4j2的日志组件,所以解决的方法就是移除掉与其冲突的log4j 1.x的slf4j-log4j12-1.7.12.jar包即可。

在移除后,我们再次重启任务,发现这下日志又可以正常输出了,至此算是解决了这个问题。

思考 & 总结

看起来我们已经完美解决这个问题了,但实际上这才刚刚开始,仅仅凭表面现象去解决问题是不够的,我们还要向深钻研和向广度类比。

比如:

常用的日志组件都有哪些?

log4j1 和 log4j2的区别是什么?

slf4j是什么,用来解决什么问题?

log4j与slf4j有什么关系?

slf4j是如何处理冲突的?

为什么同样有日志包冲突的机器,有的能够正常工作,有的却不能?

为什么同样的slf4j binding类,有的能正常输出log,有的却不能?

如何能提前发现冲突问题和避免?

只有弄懂了上面的这些问题,我们才能真正的理解这类问题的本质,这里面思考和学习的过程,对自身的提升其实是非常有益的,这也是一般工程师和优秀的工程师的差距地方。有想法的同学可以先尝试思考一下,下一篇文章我们继续分析和总结。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-09-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 我是攻城师 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 起因
  • 排查 & 解决
  • 思考 & 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档