1 SLF4J
日志行業的現狀
-
架構繁
不同類庫可能使用不同日志架構,相容難,無法接入統一日志,讓運維很頭疼!
-
配置複雜
由于配置檔案一般是 xml 檔案,内容繁雜!很多人喜歡從其他項目或網上閉眼copy!
-
随意度高
因為不會直接導緻代碼 bug,測試人員也難發現問題,開發就沒仔細考慮日志内容擷取的性能開銷,随意選用日志級别!
- Logback、Log4j、Log4j2、commons-logging及java.util.logging等,都是Java體系的日志架構。
不同的類庫,還可能選擇使用不同的日志架構,導緻日志統一管理困難。
SLF4J(Simple Logging Facade For Java)就為解決該問題而生

提供統一的日志門面API
圖中紫色部分,實作中立的日志記錄API
橋接功能
藍色部分,把各種日志架構API橋接到SLF4J API。這樣即使你的程式使用了各種日志API記錄日志,最終都可橋接到SLF4J門面API
适配功能
紅色部分,綁定SLF4J API和實際的日志架構(灰色部分)
SLF4J隻是日志标準,還是需要實際日志架構。日志架構本身未實作SLF4J API,是以需要有個前置轉換。
Logback本身就按SLF4J API标準實作,是以無需綁定子產品做轉換。
雖然可用log4j-over-slf4j實作Log4j橋接到SLF4J,也可使用slf4j-log4j12實作SLF4J适配到Log4j,也把它們畫到了一列,但是它不能同時使用它們,否則就會産生死循環。jcl和jul同理。
雖然圖中有4個灰色的日志實作架構,但業務開發使用最多的還是Logback和Log4j,都是同一人開發的。Logback可認為是Log4j改進版,更推薦使用,已是社會主流。
Spring Boot的日志架構也是Logback。那為什麼我們沒有手動引入Logback包,就可直接使用Logback?
spring-boot-starter子產品依賴spring-boot-starter-logging子產品,而
spring-boot-starter-logging自動引入logback-classic(包含SLF4J和Logback日志架構)和SLF4J的一些擴充卡。
2 異步日志就肯定能提高性能?
如何避免日志記錄成為系統性能瓶頸呢?
這關系到磁盤(比如機械磁盤)IO性能較差、日志量又很大的情況下,如何記錄日志。
2.1 案例
定義如下的日志配置,一共有兩個Appender:
- FILE是一個FileAppender,用于記錄所有的日志
- CONSOLE是一個ConsoleAppender,用于記錄帶有time标記的日志
-
一文搞懂Java日志級别,重複記錄、丢日志問題(上)1 SLF4J2 異步日志就肯定能提高性能? - 把大量日志輸出到檔案中,日志檔案會非常大,若性能測試結果也混在其中,就很難找到那條日志了。
是以,這裡使用EvaluatorFilter對日志按照标記進行過濾,并将過濾出的日志單獨輸出到控制台。該案例中給輸出測試結果的那條日志上做了time标記。
配合使用标記和EvaluatorFilter,可實作日志的按标簽過濾。
測試代碼:實作記錄指定次數的大日志,每條日志包含1MB位元組的模拟資料,最後記錄一條以time為标記的方法執行耗時日志:
執行程式後發現,記錄1000次日志和10000次日志的調用耗時,分别是5.1s和39s
對隻記錄檔案日志的代碼,這耗時過長了。
2.2 源碼解析
FileAppender繼承自OutputStreamAppender
在追加日志時,是直接把日志寫入OutputStream中,屬同步記錄日志
是以日志大量寫入才會曠日持久。如何才能實作大量日志寫入時,不會過多影響業務邏輯執行耗時而影響吞吐量呢?