日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

带你理清 Java 混乱的日志体系 - log4j、logback、log4j2、jcl、SLFJ 究竟是啥关系?

發布時間:2024/2/28 java 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 带你理清 Java 混乱的日志体系 - log4j、logback、log4j2、jcl、SLFJ 究竟是啥关系? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1.JAVA混亂的日志體系

換亂的java日志體系

case:

SLF4J-JCL

LOG4J-CORE

LOGBACK

SLF4J-SIMPLE

JCL-OVER-SLF4J

LOGBACK-CORE

LOG4J

LOG4J-API

LOG4J-JUL

LOG4J-JCL

LOGBACK-ACCESS

LOGBACK-CLASSIC

SLF4-API

SLF4J-LOGJ12

LOGBACK-CLASSIC

LOG4J-SLF4J-IMPL

1.1 JAVA日志體系概述

問題:

常用的日志框架有哪些?

大家目前正在使用的

名稱jar描述
log4jlog4j-1.2.17早期常用的日志組件
logbacklogback-core,logback-classic,logback-access性能由于log4j
log4j2log4j,log4j-api,log4j-corelog4j升級
Java.util.loggingjdkjdk實現,tomcat默認實現

開發一個類似spring框架,或者開發一個組件,如何選擇

選擇任何一種實現,都不太好,不同的日志輸出不一樣,日志也會打印多份。如何解決,日志做抽象層

1.1.1 Apache Commons Logging(JCL)

1-官網介紹 記錄組件 在編寫一個庫時,記錄信息是非常有用的。然而,外面有很多日志實現,一個庫不能把某一個特定的日志實現強加給作為庫一部分的整體應用。Logging包是不同日志實現之間的一個超薄橋梁。一個使用commons-logging API的庫可以在運行時與任何日志實現一起使用。Common-logging自帶對許多流行的日志實現的支持,為其他的日志實現編寫適配器是一項相當簡單的任務。應用程序(而不是庫)也可以選擇使用commonons-logging。雖然日志記錄實現的獨立性對應用程序來說不像庫那樣重要,但使用commons-logging確實允許應用程序在不重新編譯代碼的情況下改變到不同的日志實現。請注意,commons-logging不會嘗試初始化或終止運行時使用的底層日志實現,這是應用程序的責任。然而,許多常用的日志實現都會自動初始化;在這種情況下,應用程序可以避免包含任何特定于所使用的日志實現的代碼。 2-實現原理 org.apache.commons.logging.impl.LogFactoryImpl#discoverLogImplementation 3-缺點,只能實現一種,通過靜態綁定實現,不易擴展,適配器模式。

1.1.2 SLFJ

slf4j全 稱為Simple Logging Facade for JAVA,java簡單日志門面。類似于Apache Common-Logging,是對不同日志框架提供的一個門面封裝(是接口而非實現),可以在部署的時候不修改任何配置即可接入一種日志實現方案。但是,他在編譯時靜態綁定真正的Log庫。使用SLF4J時,如果需要使用某一種日志實現,那么你必須選擇正確的SLF4J的jar包的集合(各種橋接包)。 ----基于OSGI模塊化框架詳解 特點: 動態加載、更新、和卸載模塊而不用停止服務 實現系統的模塊化、版本化,允許多版本bundule(模塊)同時服務--注釋,很多三方jar中的MANIFEST.MF進行子描述,就是一個例子Manifest-Version: 1.0Archiver-Version: Plexus ArchiverCreated-By: Apache MavenBuilt-By: cekiBuild-Jdk: 1.8.0_121Bundle-Description: The slf4j APIBundle-Version: 1.7.30Implementation-Version: 1.7.30X-Compile-Source-JDK: 1.5X-Compile-Target-JDK: 1.5Implementation-Title: slf4j-apiBundle-ManifestVersion: 2Bundle-SymbolicName: slf4j.apiBundle-Name: slf4j-apiBundle-Vendor: SLF4J.ORGBundle-RequiredExecutionEnvironment: J2SE-1.5Automatic-Module-Name: org.slf4jExport-Package: org.slf4j;version=1.7.30, org.slf4j.spi;version=1.7.30, org.slf4j.helpers;version=1.7.30, org.slf4j.event;version=1.7.30Import-Package: org.slf4j.impl;version=1.6.0Service model允許模塊、插件相互依賴但松耦合,分享服務更簡單

1.2 常用的日志組成方案與應用場景

目前最優的方案:slf4j的異步模式+log4j2,性能好
例如,springboot+mybatis+slf4j+log4j2

1.2.1 jcl

1.2.2 slfj


jcl本來就是抽象的,slf4j能橋接jcl,是為了能夠適配。

橋接包 slfj-log4j12.jar(橋接log4j) slf4j-jdk14.jar(橋接jdk Logging) slf4j-jcl.jar(橋接jcl) log4j-slf4j-impl.jar(橋接log4j2) logback-classic.jar(橋接logback)參考項目:log-slfj

1.2.3 日志切換,適配器

如果當前系統之中再用jcl打印日志,比如spring4,但這是想加入slfj來打印日志,就會出現兩類日志輸出,如何既覺只要classpath當中指定了slfj適配器,包,即可無縫江源日志輸出轉移到slfj上來 jcl-over-slfj:轉移 jcl日志至slf4j舉例子: 組件1:mybatis---jcl+log4j 組件2:springboot----sjlf+logback 組件2:shiro----jcl+logback 默認:jcl+jul 期望結果:slfj+logback1:slfj+橋接器+實現log4j-over-slfj:轉移log4j日志至slf4jjul-over-slfj:轉移jul日志至slf4j 名稱描述相關JAR包
門面slf4jAPI接口slf4j-api.jar
橋接用于slf4j連接對應日志實現slfj-log4j12.jar,slfj-jdk14.jar,log4j-slf4j-impl,logback-classic,slf4j-jcl.jar
適配器用于將原日志輸出無縫轉移到slf4jcl-over-slf4j.jar,log4j-over-slfj,jul-over-slfj,
具體實現日志的具體實現log4j.jar,logback,log4j2,java.util.logging

1.2.4 循環依賴

如果clappsth中既有橋接器也有適配器,日志會被踢來踢去,陷入死循環

1.3.slfj+log4j2 統一系統應用日志

由于系統組件中,可能采用了不同的日志體系,spring5之前,spring采用的是apache-common-log,spring5之后,采用spring-jcl

1.4 日志規范

1. 【強制】應用中不可直接使用日志系統(Log4j、Logback)中的 API,而應依賴使用日志框架 (SLF4J、JCL--Jakarta Commons Logging)中的 API,使用門面模式的日志框架,有利于維護和 各個類的日志處理方式統一。 說明:日志框架(SLF4J、JCL--Jakarta Commons Logging)的使用方式(推薦使用 SLF4J)使用 SLF4J: import org.slf4j.Logger; import org.slf4j.LoggerFactory; private static final Logger logger = LoggerFactory.getLogger(Test.class); 使用 JCL: import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; private static final Log log = LogFactory.getLog(Test.class); 2. 【強制】所有日志文件至少保存 15 天,因為有些異常具備以“周”為頻次發生的特點。對于 當天日志,以“應用名.log”來保存,保存在/home/admin/應用名/logs/</font>目錄下, 過往日志格式為: {logname}.log.{保存日期},日期格式:yyyy-MM-dd 說明:以 mppserver 應用為例,日志保存在/home/admin/mppserver/logs/mppserver.log,歷史日志 名稱為 mppserver.log.2016-08-01 3. 【強制】應用中的擴展日志(如打點、臨時監控、訪問日志等)命名方式: appName_logType_logName.log。logType:日志類型,如 stats/monitor/access 等;logName:日志描 述。這種命名的好處:通過文件名就可知道日志文件屬于什么應用,什么類型,什么目的,也有利于歸類查 找。 說明:推薦對日志進行分類,如將錯誤日志和業務日志分開存放,便于開發人員查看,也便于通過日志對系 統進行及時監控。 正例:mppserver 應用中單獨監控時區轉換異常,如:mppserver_monitor_timeZoneConvert.log 4. 【強制】在日志輸出時,字符串變量之間的拼接使用占位符的方式。 說明:因為 String 字符串的拼接會使用 StringBuilder 的 append()方式,有一定的性能損耗。使用占位符僅 是替換動作,可以有效提升性能。 正例:logger.debug("Processing trade with id: {} and symbol: {}", id, symbol); 5. 【強制】對于 trace/debug/info 級別的日志輸出,必須進行日志級別的開關判斷。 說明:雖然在 debug(參數)的方法體內第一行代碼 isDisabled(Level.DEBUG_INT)為真時(Slf4j 的常見實現 Log4j 和 Logback),就直接 return,但是參數可能會進行字符串拼接運算。此外,如果 debug(getName()) 這種參數內有 getName()方法調用,無謂浪費方法調用的開銷。 正例: // 如果判斷為真,那么可以輸出 trace 和 debug 級別的日志 if (logger.isDebugEnabled()) {logger.debug("Current ID is: {} and name is: {}", id, getName()); } 6. 【強制】避免重復打印日志,浪費磁盤空間,務必在 log4j.xml 中設置 additivity=false。 正例:<logger name="com.taobao.dubbo.config" additivity="false">case:<logger name="com.jd" level="DEBUG"><AppenderRef ref="console"/></logger>7. 【強制】生產環境禁止直接使用 System.out 或 System.err 輸出日志或使用 e.printStackTrace()打印異常堆棧。 說明:標準日志輸出與標準錯誤輸出文件每次 Jboss 重啟時才滾動,如果大量輸出送往這兩個文件,容易 造成文件大小超過操作系統大小限制。 8. 【強制】異常信息應該包括兩類信息:案發現場信息和異常堆棧信息。如果不處理,那么通過 關鍵字 throws 往上拋出。 正例:logger.error(各類參數或者對象 toString() + "_" + e.getMessage(), e); case:不允許記錄日志后又拋出異常,因為這樣會多次記錄日志,只允許記錄一次日志 9. 【強制】日志打印時禁止直接用 JSON 工具將對象轉換成 String。 說明:如果對象里某些 get 方法被重寫,存在拋出異常的情況,則可能會因為打印日志而影響正常業務流 程的執行。 正例:打印日志時僅打印出業務相關屬性值或者調用其對象的 toString()方法。 10.【推薦】謹慎地記錄日志。生產環境禁止輸出 debug 日志;有選擇地輸出 info 日志;如果使用 warn 來記錄剛上線時的業務行為信息,一定要注意日志輸出量的問題,避免把服務器磁盤撐 爆,并記得及時刪除這些觀察日志。 說明:大量地輸出無效日志,不利于系統性能提升,也不利于快速定位錯誤點。記錄日志時請思考:這些 日志真的有人看嗎?看到這條日志你能做什么?能不能給問題排查帶來好處? 11.【推薦】可以使用 warn 日志級別來記錄用戶輸入參數錯誤的情況,避免用戶投訴時,無所適 從。如非必要,請不要在此場景打出 error 級別,避免頻繁報警。 說明:注意日志輸出的級別,error 級別只記錄系統邏輯出錯、異常或者重要的錯誤信息。 12.【推薦】盡量用英文來描述日志錯誤信息,如果日志中的錯誤信息用英文描述不清楚的話使用 中文描述即可,否則容易產生歧義。 說明:國際化團隊或海外部署的服務器由于字符集問題,使用全英文來注釋和描述日志錯誤信息。 if (logger.isDebugEnabled()) {logger.debug(); }

1.5 性能測試

1.5.1 單線程

名稱未開啟緩存,立即刷出開啟緩存,不立即刷出異步-appender-未開啟緩存,立即輸出異步appender-開啟緩存,不立即輸出
log4j87.342秒10.757秒91.75210.058秒
logback81.6175.547100.24510.69
log4j25.272/5.614/5.1965.502/5.53/5.4535.423/5.378/4.9535.063/4.74/5.246(AsyncRoot)==>5.348/5.712/4.818(Async)

1.5.2 多線程

名稱未開啟緩存,立即刷出開啟緩存,不立即刷出異步appender-未開啟緩存,立即輸出異步appender-開啟緩存,不立即輸出
log4j102.82313.32487.96610.651
logback100.8538.238111.27255.813
log4j28.164/6.94/7.0738.02/6.597/8.0098.11/7.4858.178/8.226

架構圖對比:

log4j2-AsyncLogger

Log4j2中的AsyncLogger的內部使用了Disruptor框架。 參考:https://www.cnblogs.com/yeyang/p/7944906.htmlDisruptor簡介 Disruptor是英國外匯交易公司LMAX開發的一個高性能隊列,基于Disruptor開發的系統單線程能支撐每秒600萬訂單。目前,包括Apache Strom、Log4j2在內的很多知名項目都應用了Disruptor來獲取高性能。 Disruptor框架內部核心數據結構為RingBuffer,其為無鎖環形隊列。單線程每秒能夠處理600萬訂單,Disruptor為什么這么快?a.lock-free-使用了CAS來實現線程安全 ArrayBlockingQueue使用鎖實現并發控制,當get或put時,當前訪問線程將上鎖,當多生產者、多消費者的大量并發情形下,由于鎖競爭、線程切換等,會有性能損失。 Disruptor通過CAS實現多生產者、多消費者對RingBuffer的并發訪問。CAS相當于樂觀鎖,其性能優于Lock的性能。b.使用緩存行填充解決偽共享問題 計算機體系結構中,內存的訪問速度遠遠低于CPU的運行速度,在內存和CPU之間,加入Cache,CPU首先訪問Cache中的數據,CaChe未命中,才訪問內存中的數據。 偽共享:Cache是以緩存行(cache line)為單位存儲的,當多個線程修改互相獨立的變量時,如果這些變量共享同一個緩存行,就會無意中影響彼此的性能。 關于偽共享的深度分析,可參考《偽共享,并發編程的性能殺手》這篇文章。日志輸出方式 sync 同步打印日志,日志輸出與業務邏輯在同一線程內,當日志輸出完畢,才能進行后續業務邏輯操作 Async Appender 異步打印日志,內部采用ArrayBlockingQueue,對每個AsyncAppender創建一個線程用于處理日志輸出。 Async Logger 異步打印日志,采用了高性能并發框架Disruptor,創建一個線程用于處理日志輸出。

1.6 日志的全鏈路追蹤 簡介

1.6.1 全鏈路追蹤的解決方案

全鏈路追蹤的背景

上圖是一個典型的微服務調用鏈路,面對的場景問題如下:

1-如果D服務是一個關鍵服務,返回結果錯誤,無論是日志,還是監控平臺,并不能很快捷的定位問題出現在了那里,因為不能串聯整個調用鏈路的流程

2-當對某一個服務架構升級或者改造的時候,不好評估影響范圍,不明確服務之間的依賴關系,給技術決策帶來了困難

3-性能瓶頸,整個調用鏈路那個環節耗時比較久

4-當一次請求結束后,不好確定執行順序,都給業務邏輯上的理解帶來了困難

需要解決問題:

1-串用調用鏈,快速定位問題

2-厘清服務依賴關系

3-進行各個服務接口的性能分析

4-跟蹤業務流的處理順序

已有方案

1-Google Dapper

2-Twitter Zipkin

3-Spring Cloud Sleuth

? 3-1 與springboot及spring組件無縫集成

? 3-2支持Zipkin輸出(mysql,es)

? 3-3 支持MQ和HTTP方式傳輸

1.6.2 Spring Cloud Sleuth 介紹

基本概念:

? Trace(鏈路)

? Span(跨度)

? Annotation(標注):CS(發送請求),SR(接受請求),SS(相應發送),CR(相應被客戶端接收)

架構圖

流程圖

基本概念

1.6.3 分布式日志檢索解決方案-ELK

E:Elasticsearch —存儲

L:LogStash —收集

K:Kibana —展示

流程


補充

JCL

slf4j
+jcl 或其它

總結

以上是生活随笔為你收集整理的带你理清 Java 混乱的日志体系 - log4j、logback、log4j2、jcl、SLFJ 究竟是啥关系?的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。