一次生產環境單機日誌不打印的排查過程

背景

Q 業務系統在作發佈前檢查工做時,發現一臺單機的主日誌沒有打印,而其餘生產機器的日誌表現則是正常的。api

排查流

clipboard.png

思考

經過 greys 觀察主 service 的業務入口,發現該機器線上流量的請求接受、邏輯處理、結果反饋均正常。排查範圍就聚焦在 log jar 配置上。spa

clipboard.png
clipboard.png

解決

  1. SOF搜索,找到一篇 log 綁定包衝突的排查 & 解決方法。排查本地是否存在綁定包衝突的問題,結果發現確實是的 ——

clipboard.png

  1. 引入 slf4j-log4j12-empty_version.jar,排掉其餘 jar 包引入的日誌綁定包。
  2. 發佈、部署該單機,問題解決。

原理

研究了一下 slf4j-log4j12 實現綁定的原理——簡單來講,日誌輸出到單機本地,須要如下 3 類 jar 包相互配合:日誌

  • slf4j 。業務程序調用的日誌接口,只有接口定義,沒有實現,從而保證了代碼層調用 Log 的統一
  • 日誌組件。好比 log4j-api、log4j-core,是 log4j2 的內部實現;logback-classic、logback-core,是 logback 的內部實現;log4j,是 logj4 的內部實現。它們自己是沒有衝突的,能夠並存
  • 綁定包。將 slf4j-api 的接口綁定到對應的 log 實現上,好比 slf4j-log4j十二、log4j-slf4j-impl(關鍵)

clipboard.png

具體到代碼實現上,就是經過 StaticLoggerBinder.getSingleton ( ) 方法返回的單例,實現包的綁定 ——blog

clipboard.png

qjt 程序中,同時存在着兩類綁定包:log4j-slf4j-impl-2.7.jar 和 slf4j-log4j12-1.7.2.jar。這實際是一種意義上的日誌綁定包衝突 —— 選定哪一個包,取決於 ClassLoader 先加載哪一個,具備必定的隨機性。接口

clipboard.png

  • 其餘生產機 StaticLoggerBinder 的加載狀況 —— 能夠看到使用的是 log4j-slf4j-impl-2.7.jar

clipboard.png

  • 問題單機 StaticLoggerBinder 的加載狀況 —— 能夠看到使用的是 slf4j-log4j12-1.7.2.jar

clipboard.png

核心:slf4j-log4j12 意指 slf4j 底層橋接到 log4j;log4j-slf4j-impl 意指 log4j 底層橋接到 slf4j。經過機器本地 lib 庫也能夠看到,qjt 用的 facade 是 log4j。因此若是 classloader 先加載了 slf4j-log4j12 的話,就會沒法打印日誌 —— 由於 log4j 找不到具體的橋接實現了。ip

再來看一下 slf4j-log4j12-empty_version.jar 是什麼東東。經過觀察它的包結構,能夠看到實際上是 slf4j 綁定包的空實現,由此排掉了其餘 jar 包引入的 slf4j-log4j12 實現。ssl

clipboard.png

小結

敘述到此,能夠發現正是 ClassLoader 隨機加載兩類綁定包的不一樣,從而致使了日誌打印表現的不一樣。爲了不該狀況,強烈建議各位同窗排查是否存在綁定包的衝突。部署

相關文章
相關標籤/搜索