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

異步打印日誌的一點事

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


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

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)

分享創造快樂