Log4j2異步情況下怎么防止丟日志的源碼分析以及隊列等待和拒絕策略分析



org.apache.logging.log4j.core.async.AsyncLoggerConfigDisruptor
以下所有源碼均在此類中
首先我們看下log4j2異步隊列的初始化

 

從這里面我們可以看到,使用的是單例的線程池,這里請注意,這個線程池里定義的是后台線程

並且對於線程池的實現我們不可以自定義配置,是寫死的,為什么要這樣做呢?原因是為了保證日志的順序性.

而在stop()方法也就是服務關閉的處理邏輯里,將循環條件設置為(隊列不為空&&次數<200次),每次則將線程休眠50毫秒,為什么要這樣做呢?這是為了拖延jvm的關閉,因為我們的線程池使用的是后台線程,所以刷日志線程也不會延長jvm的生命周期,因此需要一個前台線程保證jvm不會馬上關閉

 

說完這個,再說說Discuptor那邊的消費者阻塞策略,因為消費者並不是直接操作RingBuffer的,而是通過ConsumerBarrier對象間接地操作RingBuffer。像生產者一樣,Consumer要知道它的下一個讀取需要才能讀取。Consumer並不是一個個地讀取數據,而是批量讀取,舉個栗子:如果它處理完了6號slot以前的數據,那么接下來它期待處理7號slot。ConsumerBarrier返回RingBuffer的最大可訪問序號,假如是10。如果7號以后的slot還沒有數據,那么它會根據ConsumerBarrier里面的WaitStrategy策略進行等待,直到生產者生產完數據。同時,生產者每次生產完一個數據之后都會通知Consumer,而不是Consumer每次都去詢問。直到生產完10號slot的數據之后,Consumer才會一次性讀取幾個slot的數據,然后才更新自己的cursor。

它們分別是

Block:阻塞等待

Timeout: 使用LockSupport的parkNanos()方法來睡眠,好處是在睡眠的時候不會浪費CPU,壞處是因為是定時睡眠,所以會導致延遲較大

Yield: 空轉調用Thread.yield(),讓出CPU資源給其它線程,但是自己依然會去搶時間片,這個是最及時的

Sleep: 是一種混合方式,先開始spin(CPU空轉),之后沒有就緒就 Thread.yield(),在之后就會block,這個算是最佳方案吧

 關於這個如何設置

根據源碼分析到要在classpath下建立一個這個名字的文件,然后寫上這樣的屬性

 如下圖:

 

 

我們再說說隊列滿的情況下的拒絕策略吧

 

 就是這三種,第一種的意思是,繼續異步線程調用排隊,第二種的意思是,阻塞當前線程等待,第三種就是丟棄

我們可以這樣子指定

 

 或者按照官網說的這樣做就行

 

 
       


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM