公司項目采用了Log4j2來輸出日志,在開發環境和測試環境下均可以輸出日志,但在生成環境就沒有日志輸出。開始毫無頭緒,后來通過不斷的排查,終於解決了這個問題。在此記錄下該問題的解決過程,便於后續查閱。
一、發現問題
開發環境打印日志但生產環境不打印日志這個問題比較棘手。一直找不到原因,后面突然想到在啟動的時候打印信息肯定會有所不同。通過在
2個環境啟動同一個項目的控制台打印信息對比有了以下的發現:
(1)
出現了
SL4J
的警告信息,都是提示包沖突
Multiple bindings were found on the class path
(2)
但是仔細觀察發現了
加載這兩個沖突的jar包的順序不同
,具體見下圖:
①開發環境日志沖突jar包加載順序圖

防止圖失效,我把文字復制過來了
SLF4J:Class path contains mutiple SLF4J bindings
SLF4J:Found binding in[jar:file:/WEB-INF/lib/log4j-slf4j-impl-2.6.6.jar!/org/slf4j/impl/StaticLoggerBider.class]
SLF4J:Found binding in[jar:file:/WEB-INF/lib/slf4j-log4j12-1.7.22.jar!/org/slf4j/impl/StaticLoggerBider.class]
3
1
SLF4J:Class path contains mutiple SLF4J bindings
2
SLF4J:Found binding in[jar:file:/WEB-INF/lib/log4j-slf4j-impl-2.6.6.jar!/org/slf4j/impl/StaticLoggerBider.class]
3
SLF4J:Found binding in[jar:file:/WEB-INF/lib/slf4j-log4j12-1.7.22.jar!/org/slf4j/impl/StaticLoggerBider.class]
②生產環境日志沖突jar包加載順序圖

防止圖失效,我把文字復制過來了
SLF4J:Class path contains mutiple SLF4J bindings
SLF4J:Found binding in[jar:file:/WEB-INF/lib/slf4j-log4j12-1.7.22.jar!/org/slf4j/impl/StaticLoggerBider.class]
SLF4J:Found binding in[jar:file:/WEB-INF/lib/log4j-slf4j-impl-2.6.6.jar!/org/slf4j/impl/StaticLoggerBider.class]
3
1
SLF4J:Class path contains mutiple SLF4J bindings
2
SLF4J:Found binding in[jar:file:/WEB-INF/lib/slf4j-log4j12-1.7.22.jar!/org/slf4j/impl/StaticLoggerBider.class]
3
SLF4J:Found binding in[jar:file:/WEB-INF/lib/log4j-slf4j-impl-2.6.6.jar!/org/slf4j/impl/StaticLoggerBider.class]
二、分析
-
在開發環境,先加載的是 log4j-slf4j-impl ,后加載的是slf4j-log4j12。而生產環境, 先加載的是 slf4j-log4j12 ,后加載的是log4j-slf4j-impl。
-
通過查閱官方資料發現slf4j在綁定時,如果有多個可以綁定的包, SLF4J選擇綁定的方式由JVM確定,並且出於所有實際目的應該被認為是隨機的 。
-
但是 ,經過我12次在slf4j源碼打斷點測試發現slf4j優先綁定先加載的jar包。所以在開發環境slf4j綁定的是log4j-slf4j-impl這個jar包,而在生產環境中綁定的是slf4j-log4j12這個jar包。
-
通過查閱log4j2官方資料可知,slf4j集成log4j2時需要的橋接包是 log4j-slf4j-impl 。 開發環境中slf4j綁定是正確的,因此可以打印日志 。而生產環境中slf4j綁定的jar包是slf4j-log4j12。所以生產環境輸出不了日志。產生這個問題的根本原因是lib里面有多個了slf4j可綁定的jar包。
三、解決方案
由於是slf4j綁定jar包錯誤而導致打印不了日志。所以我們必須要把這個slf4j-log4j12.jar包排除干凈。這個包主要來源有:
(1)framework-logger(公司自己封裝的框架)(2)zkclient(3)zookeeper
排除完jar包后,本地進行打包。打包完成后,必須要檢查一遍,看一下生成的打包文件的lib文件夾下是否還存在slf4j-log4j12.jar。如果有,應該是jar包沒排除干凈。可以通過maven命令查看依賴樹,看看是那個依賴把這個jar給傳遞進來的。命令為:dependency:tree
四、小結
(1)使用SLF4j+Log4j2時使用的橋接包是log4j-slf4j-impl(2)當有多個SLF4j的橋接包時,一定要排除不需要的包(2)項目啟動時控制台輸出的信息很重要,耐心觀察啟動日志可以解決很多問題