1. 程式人生 > >slf4j-logback-Appender進階

slf4j-logback-Appender進階

logback 進階 
基礎篇請參考http://wangxinchun.iteye.com/blog/2094761
1、AsyncAppender。 
為了提升效能,logback 支援非同步的日誌記錄。 

關於非同步:本質就是執行不等待,所謂執行就是提交任務。任務執行 1、有結果:一般認為執行完可以回撥;2、沒有結果,執行完就完事。log的記錄就是典型的沒有結果的情況,呼叫方不需要知道執行的最終結果。 

實現: logback 是通過 ch.qos.logback.classic.AsyncAppender 來實現非同步的log日誌記錄的。其內部實現是通過儲存一個 BlockingQueue<E> blockingQueue; 來快取 (info,warn,error)的日誌訊息,然後由一個 Worker worker 執行緒 從 blockingQueue 中 blockingQueue.take();資料,並輸出到   AppenderAttachableImpl<E> aai 中。


關於BlockingQueue的使用 是非同步的重點,請參考: 
http://wangxinchun.iteye.com/blog/1882960

相關原始碼: 
Java程式碼  收藏程式碼
  1. public class AsyncAppenderBase<E> extends UnsynchronizedAppenderBase<E> implements AppenderAttachable<E> {  
  2.   //內部要輸出的appender  
  3.   AppenderAttachableImpl<E> aai = new AppenderAttachableImpl<E>();  
  4.   // log 訊息佇列  
  5.   BlockingQueue<E> blockingQueue;  
  6.   /** 
  7.    * 預設的訊息佇列,一般可以稍大一點*/  
  8.   public static final int DEFAULT_QUEUE_SIZE = 256;  
  9.   int queueSize = DEFAULT_QUEUE_SIZE;  
  10.   int appenderCount = 0;  
  11.   static final int UNDEFINED = -1;  
  12.   int discardingThreshold = UNDEFINED;  
  13.    //實際的log 輸出執行緒任務
      
  14.   Worker worker = new Worker();  
  15.   //其他略  
  16. }  

使用case: 
Java程式碼  收藏程式碼
  1.    <!-- 迴圈檔案輸出(基於時間戳的分檔案,是實際專案中用途最廣的一種情況) -->  
  2. <appender name="ROLLING_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">  
  3.    <file>rooling.log</file>  
  4.     <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">  
  5.         <fileNamePattern>rooling-log.%d{yyyy-MM-dd-HH}.log.gz</fileNamePattern>  
  6.         <maxHistory>30</maxHistory>  
  7.     </rollingPolicy>  
  8.     <encoder>  
  9.         <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n </pattern>  
  10.     </encoder>  
  11. </appender>  
  12.    <appender name="SYNC_ROLLING_FILE" class="ch.qos.logback.classic.AsyncAppender">  
  13.        <appender-ref ref="ROLLING_FILE"/>  
  14.        <queueSize>1024</queueSize>  
  15.     <discardingThreshold>0</discardingThreshold>  
  16.    </appender>  
  17. <logger name="com.qunar.logback.LogbackTest" additivity="false"  
  18.     level="debug">  
  19.      <!-- <appender-ref ref="SYNC_ROLLING_FILE" />   -->  
  20.     <appender-ref ref="ROLLING_FILE" />   
  21. </logger>  


測試: 
Java程式碼  收藏程式碼
  1. @Test  
  2.     public void testLogback() throws InterruptedException {  
  3.         long l = System.currentTimeMillis();  
  4.         for(int i=0;i<30000;i++){  
  5.             logger.debug("hello {} ""world" +i);  
  6.             logger.info("hello {} ""world"+i);  
  7.             logger.warn("hello {} ""world"+i);  
  8.             logger.error("hello {} ""world"+i);  
  9.             if(i%1000 == 0){  
  10.                 Thread.currentThread().sleep(50);  
  11.             }  
  12.         }  
  13.         System.out.println(System.currentTimeMillis() - l);  
  14.         Thread.currentThread().sleep(1000);  
  15.     }  


結論: 
同步的耗時:3800 左右 
非同步的耗時:4500 左右 
另外:考慮到實際的生產環境,大多不會把快取填滿,非同步的效能優勢會更明顯。 

請注意:如果迴圈非常快,有可能佇列很快就滿了,當前執行緒要等待work執行緒把資料輸出到appender,這樣的測試是不能顯示非同步appender的優勢的,所以i%1000==0 進行了短暫的等待。 

2、RollingFileAppender 
迴圈檔案輸出appender,特點:可以根據rollingPolicy 來指定檔名的規則,按照時間或自增id ,保證log輸出到由(%d)當前時間指定的特定的檔案內,同一個時間規則,有可以根據(%i)來根據檔案的大小分多個檔案。 

對於RollingFileAppender 一般必須要指定 rollingPolicy 和 triggeringPolicy,由於TimeBasedRollingPolicy 實現了TriggeringPolicy 和 RollingPolicy 所以如果rollingPolicy  配置為 TimeBasedRollingPolicy  ,可以不配置triggeringPolicy。 

TimeBasedRollingPolicy案例如下: 
Java程式碼  收藏程式碼
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <configuration scan="true" scanPeriod="30 seconds">  
  3.     <contextName>myAppName</contextName>  
  4.     <!-- 命令列輸出 -->  
  5.     <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">  
  6.         <encoder>  
  7.             <pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36}- %msg%n</pattern>  
  8.         </encoder>  
  9.     </appender>  
  10.     <!-- 迴圈檔案輸出(基於時間戳的分檔案,是實際專案中用途最廣的一種情況) -->  
  11.     <appender name="ROLLING_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">  
  12.         <file>rooling.log</file>  
  13.         <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">  
  14.             <fileNamePattern>rooling-log.%d{yyyy-MM-dd-HH}.%i.log.gz</fileNamePattern>  
  15.             <maxHistory>30</maxHistory>  
  16.              <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">  
  17.                 <maxFileSize>1MB</maxFileSize>  
  18.              </timeBasedFileNamingAndTriggeringPolicy>  
  19.         </rollingPolicy>  
  20.         <encoder>  
  21.             <pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36}- %msg%n</pattern>  
  22.         </encoder>  
  23.     </appender>  
  24.     <logger name="com.qunar.logback.LogbackTest" additivity="true"  
  25.         level="debug">  
  26.         <appender-ref ref="ROLLING_FILE" />  
  27.     </logger>  
  28.     <root level="INFO">  
  29.         <appender-ref ref="STDOUT" />  
  30.     </root>  
  31. </configuration>  


輸出的效果如下: 


FixedWindowRollingPolicy 
固定格式,固定檔案大小的rooling策略。 

案例如下: 
Java程式碼  收藏程式碼
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <configuration scan="true" scanPeriod="30 seconds">  
  3.     <contextName>myAppName</contextName>  
  4.     <!-- 命令列輸出 -->  
  5.     <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">  
  6.         <encoder>  
  7.             <pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36}- %msg%n</pattern>  
  8.         </encoder>  
  9.     </appender>  
  10.     <!-- 迴圈檔案輸出(基於時間戳的分檔案,是實際專案中用途最廣的一種情況) -->  
  11.     <appender name="ROLLING_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">  
  12.         <file>test.log</file>  
  13.         <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">  
  14.           <fileNamePattern>tests.%i.log.zip</fileNamePattern>  
  15.           <minIndex>1</minIndex>  
  16.           <maxIndex>3</maxIndex>  
  17.         </rollingPolicy>  
  18.          <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">  
  19.           <maxFileSize>1MB</maxFileSize>  
  20.         </triggeringPolicy>  
  21.         <encoder>  
  22.             <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n </pattern>  
  23.         </encoder>  
  24.     </appender>  
  25.     <logger name="com.qunar.logback.LogbackTest" additivity="false"  
  26.         level="debug">  
  27.         <appender-ref ref="ROLLING_FILE" />  
  28.     </logger>  
  29.     <root level="INFO">  
  30.         <appender-ref ref="STDOUT" />  
  31.     </root>  
  32. </configuration>