前言 說一個自己經歷過的事情,有一次我在開發一個通過csv文件批量導入交易的job的時候,在UAT環境上進行性能測試,發現執行失敗了。通過查看日誌發現,機器空間不足了, df h 一看發現32G的機器只有20k的空間,然後一看日誌文件的大小,就占了20G。日誌這東西,不能記得太多,不然影響性能而且占 ...
前言
說一個自己經歷過的事情,有一次我在開發一個通過csv文件批量導入交易的job的時候,在UAT環境上進行性能測試,發現執行失敗了。通過查看日誌發現,機器空間不足了,df -h一看發現32G的機器只有20k的空間,然後一看日誌文件的大小,就占了20G。日誌這東西,不能記得太多,不然影響性能而且占空間,也不能記得太少,不然出了問題,日誌查不到關鍵的信息
經驗
1. 使用直接SLF4J,而非具體的日誌框架
在項目開發中,應該在代碼中直接使用SLF4J,而非LOG4J、Logback等一些框架。SLF4J是Java里上事實上的日誌標準介面,通過門面模式,可以很方便替換具體日誌框架的實現,降低了業務代碼與日誌框架的耦合度。
2. 生產環境只列印INFO級別的日誌信息
一般而言,debug及其以下級別的信息都是沒有必要顯示出來的,除非是開發定位bug的時候。
3. 使用isDebugEanbled等相似方法降低日誌性能消耗
頻繁計算日誌是否應該記錄會對系統性能產生影響,通過顯示調用判斷是否需要列印方法如isDebugEanbled來優化性能:
if (logger.isDebugEnabled()) {
logger.debug("this is debug message");
}
4. 使用lambda表達式
該經驗針對第三條進一步優化。
如果我們簡單封裝了日誌方法,比如
public void degbug(String message) {
if (logger.isDebugEnabled()) {
logger.debug(message);
}
}
這樣雖然通過isDebugEnabled方法判斷使用需要列印日誌提高了性能,但是如果message本身是有多個字元串拼接而成的話仍然會消耗一定的資源,比如調用上文的debug方法:
debug("client" + (clientId) + "is error");
儘管使用isDebugEnabled方法,但是在該方法調用入參的時候會先拼接message這個參數,然後在調用isDebugEnabled方法進行判斷,如果此時是不需要列印的話,那麼這個拼接message的消耗就白白浪費了。應該先判斷是否需要列印,然後在拼接字元串。我們可以使用lambda表達式懶求值的特性實現:
public void degbug(Supplier<String> supplier) {
if (logger.isDebugEnabled()) {
logger.debug(supplier != null ? supplier.get() : null);
}
}
說明
基於slf4j簡單封裝,實現了以上經驗的第三、四點。