一直對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次數。日誌