logback異步輸出日誌(生產者消費者模型),並不是批量寫入日誌。

一直對logback異步輸出日誌誤解爲異步批量寫入日誌。html

今天看了源代碼。java

首先logback的異步日誌是如何配置的:app

<!--  管理端用戶行爲日誌異步輸出,異步的log片斷必須在同步段後面,不然不起做用  -->
    <appender name="ASYNC_MANAGEMENT_HABITEVENT" class="ch.qos.logback.classic.AsyncAppender">
        <!-- 不丟失日誌.默認的,若是隊列的80%已滿,則會丟棄TRACT、DEBUG、INFO級別的日誌 -->
        <discardingThreshold>0</discardingThreshold>
        <!-- 更改默認的隊列的深度,該值會影響性能.默認值爲256 -->
        <queueSize>10000</queueSize>
        <!-- 添加附加的appender,最多隻能添加一個 -->
        <appender-ref ref="MANAGEMENT_HABITEVENT"/>
    </appender>

這裏的MANAGEMENT_HABITEVENT就是普通的同步appender,能夠理解爲用異步包了一層。異步

咱們來看這個AsyncAppender,你會發現代碼很簡單,而後你看到extends,擴展至AsyncAppenderBase,絕大部分邏輯都在這個base類中。進入這個類中第一眼就看到BlockingQueue<E> blockingQueue;  還有work工做線程。基本能夠斷定是個生產者消費者模式,logback使用ArrayBlockingQueue隊列來暫存業務代碼產生的日誌。oop

再看消費者(work)的代碼:性能

class Worker extends Thread {

        public void run() {
            AsyncAppenderBase<E> parent = AsyncAppenderBase.this;
            AppenderAttachableImpl<E> aai = parent.aai;

            // loop while the parent is started
            while (parent.isStarted()) {
                try {
                    E e = parent.blockingQueue.take();    //單條循環
                    aai.appendLoopOnAppenders(e);
                } catch (InterruptedException ie) {
                    break;
                }
            }

            addInfo("Worker thread will flush remaining events before exiting. ");

            for (E e : parent.blockingQueue) {
                aai.appendLoopOnAppenders(e);
                parent.blockingQueue.remove(e);
            }

            aai.detachAndStopAllAppenders();
        }
    } 

while單條循環!!!!this

總結:logback異步輸出日誌使用了生產者消費者模型,而且是由一個消費者循環單條寫入日誌文件。線程

後話:我的理解,其實能夠擴展下,修改成批量寫入,減小IO次數。日誌

相關文章
相關標籤/搜索