起因
我们的系统上了dubbo,dubbo默认就使用的log4j1.x,之前一直用的好好的,突然有一天发现报表服务不响应请求了,但是进程并没有挂,CPU、内存都正常,最后通过jstack发现是日志的线程死锁了。官方解释在1.x的版本中,如果并发在10以上就有可能产生死锁;
转换经过
既然log4j1.x出问题了,之前用logback的时候又觉得挺爽了,那么就抓紧换吧,老规矩,方案先行。经过一番调查研究,制定如下战略:
- 加入logback的依赖;
- 排除log4j的依赖;
- 排除common-logging的依赖;
- 配置logback.xml;
- 使用maven-enforcer-plugin检查log4j和common-logging的依赖;
1. 加入logback的依赖
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>1.7.19</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-access</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>org.logback-extensions</groupId>
<artifactId>logback-ext-spring</artifactId>
<version>0.1.2</version>
<exclusions>
<exclusion>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</exclusion>
</exclusions>
</dependency>
对上面的几个jar解释下:
- jcl-over-slf4j:把common-logging.jar桥接到slf4j,因为很多第三方jar包使用的是jcl的api;
- logback-classic、ch.qos.logback:这两个是logback的jar,只要是用logback,就需要这两个包;
- log4j-over-slf4j:把log4j1.x.jar桥接到slf4j,因为很多第三方jar包使用的是log4j1.x的api;
- logback-ext-spring:logback为支持spring提供的扩展包;
2. 排除log4j的依赖
这个可以通过idea的maven插件的Show Dependencies功能查看有那些包依赖了log4j,然后一一配置exclusion。maven本身没有全局排除的功能,这个确实比较郁闷。另外发现有神人说可以通过在私服上发布一个空的相同groupId+artifactId的jar来替换掉这些依赖,个人感觉还是有点难以接受,感兴趣的同学可以去试试。
3.排除common-logging的依赖
步骤同上一步;
4.配置logback.xml
具体配置的内容就不贴了,有兴趣的看官方文档。这里面关于logger的配置特别说明一下,在网上看到很多示例配置都是错的。
<logger name="cc.humor.logback" level="ERROR" additivity="true"/>
logger的additivity如果设置成false的话(默认是true),那么一定要给logger加上appender,否则符合该规则的日志都不会输出。
<logger name="cc.humor.logback" level="INFO" additivity="false">
<appender-ref ref="STDOUT"/>
<appender-ref ref="FILE"/>
</logger>
5.使用maven-enforcer-plugin检查log4j和common-logging的依赖
使用该插件后,在编译的时候就会检查是否有log4j和common-logging的包被依赖了,如果有则编译会不通过(虽然不能做全局的排除,但是好歹做个全局检查吧 -_-!!!)。
但这里也有个不爽的地方,父子项目是不能继承的,每个项目都需要设置;
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>3.0.0-M1</version>
<executions>
<execution>
<id>enforce-banned-dependencies</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<bannedDependencies>
<excludes>
<exclude>log4j:log4j</exclude>
<exclude>commons-logging:commons-logging</exclude>
</excludes>
<searchTransitive>true</searchTransitive>
<message>must exclude log4j and commons-logging</message>
</bannedDependencies>
</rules>
<fail>true</fail>
</configuration>
</execution>
</executions>
</plugin>
总结
网上以讹传讹的资料比较多,很多官方的资料又不是很好找,所以还是小做一番总结。如果有谁想把dubbo+spring+springMVC的框架的log4j转换到logback的话,希望这篇文章能帮到你。
网友评论