0、背景
近日對公司項目引入消息隊列,對不要求即時返回的寫場景進行了改造。
因為目前對kafka的學習比較深入了,加上對往期項目中引入kafka的經歷的總結,這一過程比較順利。
美中不足的是,由於在日志監控分析層面,已應用了ELK的日志收集、存儲、展示分析技術棧,故希望在最小限度修改的前提下對消息隊列的消費日志做統一的收集和整理,因而出現了多項目寫入同一日志文件的需求。
相關環境說明如下:
JDK 1.8
springboot+springcloud 1.5.13.RELEASE
logback 1.1.11
各微服務依賴一個基礎jar包
同一機器部署多個微服務
1、過程
測試中發現消息隊列消費正常,分析日志時發現某個服務消費的topic沒有日志,進而定位到一個logback RollingFileAppender很神奇的情況。
比如今天是4月9日,它卻能穩定的把一部分日志記到今天的日志、把另一部分記到4月8日的滾動日志。
自然昨日的日志文件不在filebeat的收集列表之中,表現如同沒有記錄過。
一個正常,一個就像是被擠到昨天的日志文件了一樣。
發生頻率方面,啟動服務時有時出現問題,0點切日時穩定復現問題。
關鍵的條件:多個項目共用一個寫入的日志路徑。
2、解決方案
在查找過程中,首先翻閱到很多糾結logback相對路徑的問題。。
接下來看到logback提供的RollingFileAppender允許多進程寫入方案:prudent選項。但是,由於不能配置file選項導致需要涉及到logstash配置變更、改動成本較大。
在反復調整搜索關鍵詞后,終於:
“眼前有景道不得,崔顥題詩在上頭。”前人之述備矣!
https://blog.csdn.net/Abysscarry/article/details/102847754
“崔兄”的場景在於不停機部署以及進程級別的故障轉移,與我而言這也是一個很好的、尚未實現的努力方向。
最后參照項目中“添加與開源框架包路徑相同的類”解決問題。后續保持觀察。
3、備忘
(1)每有一條日志打印時,TimeBasedRollingPolicy都會去判斷是否需要滾動,發現滿足條件后就執行滾動操作。而我們第一感覺會認為0點判斷吧。
(2)FileOutputStream構造函數中調用的native方法會自動創建文件。
(3)關於重復類加載
類被加載時,會先判斷類是否已經被加載。第二個相同類不被載入。
項目使用Maven管理依賴時,類加載順序按照pom.xml內使用的順序(由上至下,靠上優先加載);且父POM使用的依賴會被最后加載
https://blog.csdn.net/jason20ming/article/details/7192486
簡單驗證了一下,只要在項目引用的基礎jar包中創建包名相同的類,然后保持在微服務項目的pom中首先引用基礎jar包即可。
而spring-boot-starter作為parent,其所包含的logback模塊會在最后加載。這樣當ClassLoader發現TimeBasedRollingPolicy已加載時就不會再載入logback模塊的同名文件了。
如果仍擔心,把spring-boot-starter依賴的logback exclude掉,然后在pom底部單獨引用也可以。這樣穩定適用由上至下的順序規則。