log4j2 log asynchronous printing

 

log4j2 supports asynchronous log printing. The advantage of asynchronous log output is that using a separate process to execute the log printing function can improve the log execution efficiency and reduce the impact of the log function on normal business.

Asynchronous logging needs to load disruptor-3.0.0.jar or higher on the program's classpath .

Asynchronous Loggers is a new feature in Log4j 2. It can be fully asynchronous or mixed with synchronization. It can also be used to only asynchronously append Appenders to improve system performance. Official data shows that mixing is not as effective as fully asynchronous.

 

1. Completely asynchronous mode: This asynchronous logging method does not need to modify the original configuration file. Logger still uses <root> and <logger> only need to add a system attribute code at the beginning of the main program code:

System.setProperty("Log4jContextSelector", "org.apache.logging.log4j.core.async.AsyncLoggerContextSelector");

Or set startup parameters:

-DLog4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector


2.
Asynchronous and non-asynchronous mixed output mode Logger uses <asyncRoot> or <asyncLogger> in the configuration file , and <asyncRoot> or <asyncLogger> can be mixed with <root> or <logger> . <!--[if !supportLineBreakNewLine]--> <!--[endif]-->



<?xml version="1.0" encoding="UTF-8"?><!-- No need to set system property "Log4jContextSelector" to any valuewhen using <asyncLogger> or <asyncRoot>. --><Configuration status="WARN">         <Appenders>                 <!-- Async Loggers will auto-flush in batches, so switch off immediateFlush. -->                 <RandomAccessFile name="RandomAccessFile" fileName="asyncWithLocation.log"                 immediateFlush="false" append="false">                          <PatternLayout>                                   <Pattern>%d %p %class{1.} [%t] %location %m %ex%n</Pattern>                          </PatternLayout>                 </RandomAccessFile>         </Appenders>
 


 










         <Loggers>
                 <!-- pattern layout actually uses location, so we need to include it -->
                 <AsyncLogger name="com.foo.Bar" level="trace" includeLocation="true">
                          <AppenderRef ref="RandomAccessFile"/>
                 </AsyncLogger>
                 <Root level="info" includeLocation="true">
                          <AppenderRef ref="RandomAccessFile"/>
                 </Root>
         </Loggers>
</Configuration>

这里需要注意的是,如果使用<asyncRoot> <asyncLogger>includeLocation="true"是必须要设置才会有类路径等一些信息打印出来。


3
,只异步化Appender
<Appenders>标签里增加如下<Async>标签
<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

<Async name="asyncAppender" includeLocation="true">
    <AppenderRef ref="RandomAccessFile"/>
</Async>

然后在<Root>或者<Logger>标签中引用asyncAppender即可,这里includeLocation是增加在<Async>标签中的。
<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

<Root level="info">
<AppenderRef ref="RandomAccessFile"/>
</Root>


无论是完全异步模式还是混合模式,在Appender标签中,immediateFlush属性无论为true或者false,效果都是和设置false是一样的。


4
,性能对比
完全异步 > 混合模式 > 只异步化Appender > 同步


5
,疑问
使用混合异步模式进行多线程写日志测试的时候,偶尔会出现日志没有写完的情况。是不是主线程执行完了,不会等待写日志的线程执行完,就把进程给停掉了?在主线程的最后sleep几秒,就没有再出现日志写不完的情况了。
 

 

 首先disruptor是特别适用于对时间高度敏感的多线程应用。如果app对时间不敏感完全可以不用disruptor 而只用array blocking queue. 再如果废了好大劲挣回来30毫秒,结果被一个数据库连接耗掉1秒,也没必要用。所以搞清楚适用的环境很重要。

其次这个技术其实很酷的。最酷的地方不是ring buffer 而是想到直接用CPU指令做CAS. Ring buffer是做了工程级别的优化,对于CPU branch prediction更友好。也就是我们说的cache friendly。其他的别人没提到的好处是可以replay ,这样对daily regression test很方便。

实际适用的例子随便举两个。 一个是实时的Reuters 市场数据接收,redistribute 到其他进程或者线程。另一个是如果algo model 决定place order or pull order from the market,就需要以最快的方式给市场发指令。在一个是比较复杂一点:多个ring buffer穿起来形成一个小型producer consumer 工作流,这个用的人应该不算多我就不白虎了。
http://ifeve.com/disruptor/
 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326177040&siteId=291194637