天天看點

一文搞懂Java日志級别,重複記錄、丢日志問題(上)1 SLF4J2 異步日志就肯定能提高性能?

1 SLF4J

日志行業的現狀

  • 架構繁

    不同類庫可能使用不同日志架構,相容難,無法接入統一日志,讓運維很頭疼!

  • 配置複雜

    由于配置檔案一般是 xml 檔案,内容繁雜!很多人喜歡從其他項目或網上閉眼copy!

  • 随意度高

    因為不會直接導緻代碼 bug,測試人員也難發現問題,開發就沒仔細考慮日志内容擷取的性能開銷,随意選用日志級别!

  • Logback、Log4j、Log4j2、commons-logging及java.util.logging等,都是Java體系的日志架構。

不同的類庫,還可能選擇使用不同的日志架構,導緻日志統一管理困難。

SLF4J(Simple Logging Facade For Java)就為解決該問題而生

一文搞懂Java日志級别,重複記錄、丢日志問題(上)1 SLF4J2 異步日志就肯定能提高性能?

提供統一的日志門面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為标記的方法執行耗時日志:

一文搞懂Java日志級别,重複記錄、丢日志問題(上)1 SLF4J2 異步日志就肯定能提高性能?

執行程式後發現,記錄1000次日志和10000次日志的調用耗時,分别是5.1s和39s

一文搞懂Java日志級别,重複記錄、丢日志問題(上)1 SLF4J2 異步日志就肯定能提高性能?

對隻記錄檔案日志的代碼,這耗時過長了。

2.2 源碼解析

FileAppender繼承自OutputStreamAppender

一文搞懂Java日志級别,重複記錄、丢日志問題(上)1 SLF4J2 異步日志就肯定能提高性能?

在追加日志時,是直接把日志寫入OutputStream中,屬同步記錄日志

一文搞懂Java日志級别,重複記錄、丢日志問題(上)1 SLF4J2 異步日志就肯定能提高性能?

是以日志大量寫入才會曠日持久。如何才能實作大量日志寫入時,不會過多影響業務邏輯執行耗時而影響吞吐量呢?