log4j平稳升级到log4j2

 

v一、前言

  公司中的项目虽然已经用了很多的新技术了,但是日志的底层框架还是log4j,个人还是不喜欢用这个的。最近项目再生产环境上由于log4j引起了一场血案,于是决定升级到log4j2。

v二、现象

  虽然生产环境有多个结点分散高并发带来的压力,但是消息中心上一周好多接入方接入,导致并发量一下就增多了,导致服务卡死。在堆栈信息中看到大量的BLOCK异常,如下。

复制代码
"http-nio-172.17.20.113-28080-exec-6452" #381905 daemon prio=5 os_prio=0 tid=0x00007f49e857e000 nid=0x8427f waiting for monitor entry [0x00007f49c1c75000]    java.lang.Thread.State: BLOCKED (on object monitor)     at org.apache.log4j.Category.callAppenders(Category.java:204)     - waiting to lock <0x00000000e5915bd8> (a org.apache.log4j.spi.RootLogger)     at org.apache.log4j.Category.forcedLog(Category.java:391)     at org.apache.log4j.Category.log(Category.java:856)     at org.slf4j.impl.Log4jLoggerAdapter.log(Log4jLoggerAdapter.java:581)     at com.cmos.core.logger.DefaultLogger.log(DefaultLogger.java:385)     at com.cmos.core.logger.DefaultLogger.log(DefaultLogger.java:398)     at com.cmos.core.logger.DefaultLogger.doLog(DefaultLogger.java:350)     at com.cmos.core.logger.DefaultLogger.info(DefaultLogger.java:200)     at com.cmos.core.logger.DefaultLogger.info(DefaultLogger.java:195) "http-nio-172.17.20.113-28080-exec-6452" #381905 daemon prio=5 os_prio=0 tid=0x00007f49e857e000 nid=0x8427f waiting for monitor entry [0x00007f49c1c75000]    java.lang.Thread.State: BLOCKED (on object monitor)     at org.apache.log4j.Category.callAppenders(Category.java:204)     - waiting to lock <0x00000000e5915bd8> (a org.apache.log4j.spi.RootLogger)     at org.apache.log4j.Category.forcedLog(Category.java:391)     at org.apache.log4j.Category.log(Category.java:856)     at org.slf4j.impl.Log4jLoggerAdapter.log(Log4jLoggerAdapter.java:581)     at com.cmos.core.logger.DefaultLogger.log(DefaultLogger.java:385)     at com.cmos.core.logger.DefaultLogger.log(DefaultLogger.java:398)     at com.cmos.core.logger.DefaultLogger.doLog(DefaultLogger.java:350)     at com.cmos.core.logger.DefaultLogger.info(DefaultLogger.java:200)     at com.cmos.core.logger.DefaultLogger.info(DefaultLogger.java:195)
复制代码

v三、log4j高并发线程block原因

  log4j-1.2.16 Category forcedLog逻辑如下

  

  

  log4j版本1.x中,使用的是synchronized(this)进行同步操作,所有线程共用一个Category,而它通过log4j.properties指定。 同一个Category下的线程打log时,需要进行全局同步,因此它的效率会很低,log4j 1.x版不适合高并发的场景。

  为了杜绝这种现象的发生,最好升级到log4j2,或者更换为logback。

v四、log4j2和logback选择

  到底是升级到log4j2呢,还是将底层日志框架更换为logback呢?

  检查了一下项目直接使用log4j Logger的情况,发现部分工具类中使用了(这倒没有问题,可以统一改一下),没有想到是系统部封装的框架中居然也直接使用了log4j 的Logger,心里顿时说了一声“草尼玛啊...”。

       既然是这样的话,肯定不能使用logback了,也不能直接升级成log4j2了。

v五、log4j1 如何平滑升级到log4j2

  The Log4j 1.2 Bridge allows applications coded to use Log4j 1.2 API to use Log4j 2 instead.

  1.依赖如下

复制代码
<dependency>    <groupId>org.apache.logging.log4j</groupId>    <artifactId>log4j-1.2-api</artifactId>    <version>2.6.2</version></dependency>
复制代码

  我们看一下 log4j-1.2-api-2.6.2 Category forcedLog逻辑如下,并没有调用callAppenders方法。

  

  Log4j2 包含了基于 LMAX Disruptor(高性能线程间消息通信库)的下一代 Asynchronous Loggers。在多线程环境下,Asynchronous Loggers 的吞吐量是 Log4j1 和 Logback 的 18 倍,而延迟时间也要低一个数量级。

  相信大家已经明白了,log4j-1.2-api-2.6.2桥接的原理就是复写了log4j-1.2.16相关的类,再输出日志的时候调用的是log4j2中的方法。

  2.删除掉 log4j的依赖

  3.将log4j.properties 替换成 log4j2.xml

  log4j.properties内容如下

复制代码
log4j.rootLogger=

                    
                
50000+
5万行代码练就真实本领
17年
创办于2008年老牌培训机构
1000+
合作企业
98%
就业率

联系我们

电话咨询

0532-85025005

扫码添加微信