起因
我們的系統(tǒng)上了dubbo砚亭,dubbo默認(rèn)就使用的log4j1.x,之前一直用的好好的殴玛,突然有一天發(fā)現(xiàn)報(bào)表服務(wù)不響應(yīng)請(qǐng)求了捅膘,但是進(jìn)程并沒(méi)有掛,CPU滚粟、內(nèi)存都正常寻仗,最后通過(guò)jstack發(fā)現(xiàn)是日志的線(xiàn)程死鎖了。官方解釋在1.x的版本中坦刀,如果并發(fā)在10以上就有可能產(chǎn)生死鎖愧沟;
轉(zhuǎn)換經(jīng)過(guò)
既然log4j1.x出問(wèn)題了,之前用logback的時(shí)候又覺(jué)得挺爽了鲤遥,那么就抓緊換吧沐寺,老規(guī)矩,方案先行盖奈。經(jīng)過(guò)一番調(diào)查研究混坞,制定如下戰(zhàn)略:
- 加入logback的依賴(lài);
- 排除log4j的依賴(lài)钢坦;
- 排除common-logging的依賴(lài)究孕;
- 配置logback.xml;
- 使用maven-enforcer-plugin檢查log4j和common-logging的依賴(lài)爹凹;
1. 加入logback的依賴(lài)
<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>
對(duì)上面的幾個(gè)jar解釋下:
- jcl-over-slf4j:把common-logging.jar橋接到slf4j厨诸,因?yàn)楹芏嗟谌絡(luò)ar包使用的是jcl的api;
- logback-classic禾酱、ch.qos.logback:這兩個(gè)是logback的jar微酬,只要是用logback绘趋,就需要這兩個(gè)包;
- log4j-over-slf4j:把log4j1.x.jar橋接到slf4j颗管,因?yàn)楹芏嗟谌絡(luò)ar包使用的是log4j1.x的api陷遮;
- logback-ext-spring:logback為支持spring提供的擴(kuò)展包;
2. 排除log4j的依賴(lài)
這個(gè)可以通過(guò)idea的maven插件的Show Dependencies功能查看有那些包依賴(lài)了log4j垦江,然后一一配置exclusion帽馋。maven本身沒(méi)有全局排除的功能,這個(gè)確實(shí)比較郁悶比吭。另外發(fā)現(xiàn)有神人說(shuō)可以通過(guò)在私服上發(fā)布一個(gè)空的相同groupId+artifactId的jar來(lái)替換掉這些依賴(lài)绽族,個(gè)人感覺(jué)還是有點(diǎn)難以接受,感興趣的同學(xué)可以去試試梗逮。
3.排除common-logging的依賴(lài)
步驟同上一步项秉;
4.配置logback.xml
具體配置的內(nèi)容就不貼了,有興趣的看官方文檔慷彤。這里面關(guān)于logger的配置特別說(shuō)明一下娄蔼,在網(wǎng)上看到很多示例配置都是錯(cuò)的。
<logger name="cc.humor.logback" level="ERROR" additivity="true"/>
logger的additivity如果設(shè)置成false的話(huà)(默認(rèn)是true)底哗,那么一定要給logger加上appender岁诉,否則符合該規(guī)則的日志都不會(huì)輸出。
<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的依賴(lài)
使用該插件后跋选,在編譯的時(shí)候就會(huì)檢查是否有l(wèi)og4j和common-logging的包被依賴(lài)了涕癣,如果有則編譯會(huì)不通過(guò)(雖然不能做全局的排除,但是好歹做個(gè)全局檢查吧 -_-!!!)前标。
但這里也有個(gè)不爽的地方坠韩,父子項(xiàng)目是不能繼承的,每個(gè)項(xiàng)目都需要設(shè)置炼列;
<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>
總結(jié)
網(wǎng)上以訛傳訛的資料比較多只搁,很多官方的資料又不是很好找,所以還是小做一番總結(jié)俭尖。如果有誰(shuí)想把dubbo+spring+springMVC的框架的log4j轉(zhuǎn)換到logback的話(huà)氢惋,希望這篇文章能幫到你。