Log4j2异步日志 与 垃圾回收

异步日志
log4j2最大的特点就是异步日志,其性能的提升主要也是从异步日志中受益,我们来看看如何使用log4j2的异步日志。

  • 同步日志

Log4j2异步日志 与 垃圾回收

  • 异步日志
    Log4j2异步日志 与 垃圾回收

Log4j2提供了两种实现日志的方式,一个是通过AsyncAppender,一个是通过AsyncLogger,分别对应前面我们说的Appender组件和Logger组件。

注意:配置异步日志需要添加依赖

<!--异步日志依赖-->
        <dependency>
            <groupId>com.lmax</groupId>
            <artifactId>disruptor</artifactId>
            <version>3.3.4</version>
        </dependency>
  1. AsyncAppender方式
    AsyncLogger才是log4j2 的重头戏,也是官方推荐的异步方式。它可以使得调用Logger.log返回的更快。你可以有两种选择:全局异步和混合异步。
<?xml version="1.0" encoding="UTF-8"?> 
<Configuration status="warn"> 
    <properties> 
        <property name="LOG_HOME">D:/logs</property> 
    </properties> 
    <Appenders> 
        <File name="file" fileName="${LOG_HOME}/myfile.log"> 
            <PatternLayout> 
                <Pattern>%d %p %c{1.} [%t] %m%n</Pattern> 
            </PatternLayout> 
        </File> 
        <Async name="Async"> 
            <AppenderRef ref="file"/> 
        </Async> 
    </Appenders> 
    <Loggers> 
        <Root level="error">
            <AppenderRef ref="Async"/> 
        </Root> 
    </Loggers> 
</Configuration>
  1. AsyncLogger方式
    AsyncLogger才是log4j2 的重头戏,也是官方推荐的异步方式。它可以使得调用Logger.log返回的更快。你可以有两种选择:全局异步和混合异步。

全局异步就是,所有的日志都异步的记录,在配置文件上不用做任何改动,只需要添加一个log4j2.component.properties 配置;

Log4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerCon textSelector

混合异步就是,你可以在应用中同时使用同步日志和异步日志,这使得日志的配置方式更加灵活。

<?xml version="1.0" encoding="UTF-8"?> 
<Configuration status="WARN"> 
    <properties> 
        <property name="LOG_HOME">D:/logs</property> 
    </properties> 
    <Appenders> 
        <File name="file" fileName="${LOG_HOME}/myfile.log"> 
            <PatternLayout> 
                <Pattern>%d %p %c{1.} [%t] %m%n</Pattern> 
            </PatternLayout> 
        </File> 
        <Async name="Async"> 
            <AppenderRef ref="file"/> 
        </Async> 
    </Appenders> 
    <Loggers> 
        <AsyncLogger name="com.huan" level="trace" includeLocation="false" additivity="false"> 
            <AppenderRef ref="file"/> 
        </AsyncLogger>
     	<Root level="info" includeLocation="true"> 
        	<AppenderRef ref="file"/> 
    	</Root> 
	</Loggers> 
</Configuration>

如上配置: com.huan 日志是异步的,root日志是同步的。
使用异步日志需要注意的问题:

  1. 如果使用异步日志,AsyncAppender、AsyncLogger和全局日志,不要同时出现。性能会和AsyncAppender一致,降至最低。
  2. 设置includeLocation=false ,打印位置信息会急剧降低异步日志的性能,比同步日志还要慢。

Log4j2的性能

Log4j2最牛的地方在于异步输出日志时的性能表现,Log4j2在多线程的环境下吞吐量与Log4j和Logback的比较如下图。下图比较中Log4j2有三种模式:
1)全局使用异步模式;
2)部分Logger采用异步模式;
3)异步Appender。可以看出在前两种模式下,Log4j2的性能较之Log4j和Logback有很大的优势。

Log4j2异步日志 与 垃圾回收

无垃圾记录

垃圾收集暂停是延迟峰值的常见原因,并且对于许多系统而言,花费大量精力来控制这些暂停。

许多日志库(包括以前版本的Log4j)在稳态日志记录期间分配临时对象,如日志事件对象,字符串,字符数组,字节数组等。这会对垃圾收集器造成压力并增加GC暂停发生的频率。

从版本2.6开始,默认情况下Log4j以“无垃圾”模式运行,其中重用对象和缓冲区,并且尽可能不分配临时对象。还有一个“低垃圾”模式,它不是完全无垃圾,但不使用ThreadLocal字段。

Log4j 2.6中的无垃圾日志记录部分通过重用ThreadLocal字段中的对象来实现,部分通过在将文本转换为字节时重用缓冲区来实现。

使用Log4j 2.5:内存分配速率809 MB /秒,141个无效集合。

Log4j2异步日志 与 垃圾回收
Log4j 2.6没有分配临时对象:0(零)垃圾回收。

Log4j2异步日志 与 垃圾回收
有两个单独的系统属性可用于手动控制Log4j用于避免创建临时对象的机制:

log4j2.enableThreadlocals - 如果“true”(非Web应用程序的默认值)对象存储在ThreadLocal字段中并重新使用,否则将为每个日志事件创建新对象。

log4j2.enableDirectEncoders - 如果将“true”(默认)日志事件转换为文本,则将此文本转换为字节而不创建临时对象。

注意: 由于共享缓冲区上的同步,在此模式下多线程应用程序的同步日志记录性能可能更差。如果您的应用程序是多线程的并且日志记录性能很重要,请考虑使用异步
记录器。

上一篇:如何在tomcat上部署多个Spring Boot应用程序时指定logging.config


下一篇:log4j2文件配置