歡迎光臨
每天分享高質量文章

非同步列印日誌的一點事

(點選上方公眾號,可快速關註)


來源:今天你不奮鬥明天你就落後 ,

www.jianshu.com/p/900d433051e6

一、前言

最近剛剛結束轉崗以來的第一次雙11壓測,收穫頗多,難言言表, 本文就先談談非同步日誌吧,在高併發高流量響應延遲要求比較小的系統中同步打日誌已經滿足不了需求了,同步打日誌會阻塞呼叫打日誌的執行緒,而打日誌本身是需要寫磁碟的,所以會造成rt增加。非同步日誌就是為瞭解決這個問題。

二、日誌列印模型

同步日誌模型

如上圖,多個業務執行緒列印日誌時候要等把內容寫入磁碟後才會傳回,所以打日誌的rt就是寫入磁碟的耗時。

非同步日誌模型

如上圖多個業務執行緒列印日誌時候是把列印任務放入記憶體佇列後就直接傳回了,而具體列印日誌是有日誌系統的一個日誌執行緒去佇列裡面獲取然後執行,可見這種列印rt就是寫入記憶體佇列的耗時。

三、關於非同步日誌的一些事

非同步日誌設定

對於logback來說非同步日誌裡面的佇列是一個有界ArrayBlockingQueue,其中queueSize是佇列大小,taskLogAppender是取用的普通同步日誌

discardingThreshold是一個閾值,透過下麵程式碼看他的作用:

當佇列的剩餘容量小於這個閾值並且當前日誌level TRACE, DEBUG or INFO ,則丟棄這些日誌。

在壓測時候程式碼配置如上,也就是配置了非同步日誌,但是還是出現了執行緒阻塞在打日誌的地方了,經檢視是阻塞到了日誌佇列ArrayBlockingQueue的put方法:

可知put方法在佇列滿時候會掛起當前執行緒。那麼如何解那?

上面介紹了discardingThreshold,可知本文設定為0說明永遠不會丟棄日誌level TRACE, DEBUG or INFO的日誌,只要discardingThreshold>0則當佇列快滿時候level TRACE, DEBUG or INFO的日誌就會丟棄掉,這個貌似可以解決問題。但是如果列印的是warn級別的日誌那?還是會在put的時候阻塞。

透過看程式碼發現最終寫日誌時候有個判斷:

如果設定了neverBlock=true則寫日誌佇列時候會呼叫ArrayBlockingQueue對的offer方法而不是put,而offer是非阻塞的:

可知如果佇列滿則直接傳回,而不是被掛起當前執行緒。

所以配置非同步appender時候如下:

四 、總結

在高併發低延遲要求的系統裡面不重要的日誌可以設定為非同步並且要註意設定佇列滿則丟棄策略,防止業務執行緒被掛起從而影響rt。

【關於投稿】


如果大家有原創好文投稿,請直接給公號傳送留言。


① 留言格式:
【投稿】+《 文章標題》+ 文章連結

② 示例:
【投稿】《不要自稱是程式員,我十多年的 IT 職場總結》:http://blog.jobbole.com/94148/

③ 最後請附上您的個人簡介哈~



看完本文有收穫?請轉發分享給更多人

關註「ImportNew」,提升Java技能

贊(0)

分享創造快樂