踩坑記(1)——使用slf4j+logback記錄日誌

 剛開始的jar包版本以下,由於選擇jar包版本不一樣致使的一些坑,踩過了就記錄下來:java

<spring.version>3.1.0.RELEASE</spring.version>
<slf4j.version>1.7.25</slf4j.version>
<logback.version>1.2.3</logback.version>
<logback.ext.version>0.1.1</logback.ext.version>

commons-logging:scope爲provided,這樣是爲了打包時不會被帶上,也就是不使用commons-logging而是準備使用slf4j
jcl-over-slf4j:這個是橋接包,將已經使用commons-logging記錄日誌又無法改變(spring默認使用的就是commons-logging)的jar包的日誌橋接到slf4
slf4j-api:這就是咱們要用的slf4j的日誌接口,其實和commons-logging同樣都是接口,不是具體實現
logback-classic:具體的日誌實現,真正記錄日誌的jar
logback-ext-spring:爲了將logback和spring集成而使用的包,若是不用這個包也能夠記錄日誌,但會有個問題(下文會說)web

<!-- log -->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>${commons-logging.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
</dependency>
<dependency>
<groupId>org.logback-extensions</groupId>
<artifactId>logback-ext-spring</artifactId>
<version>${logback.ext.version}</version>
</dependency>

準備好依賴後,開始配置logback的使用環境
在web.xml中配置logback的監聽器,ch.qos.logback.ext.spring.web.LogbackConfigListener類就是logback-ext-spring.jar中的
logback默認也會查找幾個地方的配置文件,不過我喜歡自定義路徑,畢竟並非全部公司都會講配置所有放到resources目錄下而是統一在硬盤上進行的管理spring

<!-- logback -->
<context-param>
<param-name>logbackExposeWebAppRoot</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<param-name>logbackConfigLocation</param-name>
<param-value>file:/opt/config/testservice/logback.xml</param-value>
</context-param>
<listener>
<listener-class>ch.qos.logback.ext.spring.web.LogbackConfigListener</listener-class>
</listener>

問題一:
程序正常啓動,原本很開心的一件事,卻遇到了轉折,當改了java文件的代碼並保存後,tomcat熱部署reload會致使在項目從新加載過程當中爆出異常——說可能致使內存泄露??納裏,表示徹底是懵逼的api

靜下心看了看,發現竟然是logback-1這個線程在重載的過程當中沒有被釋放掉,那麼每重載一次就會多出一個logback線程,固然也就會形成內存泄露了;在eclipse的debug視圖的dubug窗口中查看線程,確實也是這種狀況,重載前只有一個logback-1線程,重載後卻有兩個同名的logback-1了:tomcat

重載後以下圖,報出內存泄露異常也是對的多線程

那麼什麼緣由形成的呢?我跟着監聽器ch.qos.logback.ext.spring.web.LogbackConfigListener跟了下代碼,發現是contextDestroyed執行時報錯,因此也懶得深究緣由了(其實就是代碼寫的有問題,在logback-ext-spring的0.1.2版本修復了)。eclipse

 

將logback-ext-spring從0.1.1替換到0.1.2(高於0.1.1就行)問題就解決了,看來這個jar包的做者也發現這個問題並修復了。我最後使用的版本就是<logback.ext.version>0.1.3</logback.ext.version>;徹底看本身了最高版本目前是0.1.4而個人spring是3.1的最高只能和0.1.3的一塊兒使用。maven

 

問題二:ide

     當解決了問題一後,覺得終於能夠好好玩耍了(其實徹底能夠正常玩耍了,只是強迫症。。。);一樣看了下debug視圖的debug窗口,發現剛啓動的時候只有一個logback-1線程spa

以後,每一分鐘會多出一個logback-n線程,一共會多出到logback-8,記一個日誌有必要這麼多線程麼?

 

剛開始覺得是哪裏代碼又問題,後來一想不可能,啓動後什麼也沒作就慢慢增長,因此猜想是logback內部有什麼貓膩,而後找到了logback-core內部建立線程池的地方,果真發現指定了常駐線程池的線程數

 

JDK文檔,明確寫了「保留在池中的線程數」,這個我是以爲有點多了,因此我就開始找低版本的

發現CoreConstants類中SCHEDULED_EXECUTOR_POOL_SIZE這個常量隨着版本在變化,以下:

1.1.9以上     8
1.1.8       2
1.1.7       2
1.1.6及如下   無

最終分析,我的以爲不必開啓常駐內存8個線程來記錄日誌,因此我選擇了1.1.7(參考maven倉庫使用記錄,選擇使用人數較多的)

最終肯定jar包版本:

<spring.version>3.1.0.RELEASE</spring.version>
<slf4j.version>1.7.25</slf4j.version>
<logback.version>1.1.7</logback.version>
<logback.ext.version>0.1.3</logback.ext.version>

總結:jar包並非越新越好,而是要看你用了哪些功能,以上來就使用最新的包每每會出現一些與預期不一致的效果,解決起來又比較頭疼~~

 

 

 

最終肯定jar包版本:

相關文章
相關標籤/搜索