当前位置: > > > SpringBoot - 日志框架Log4j2的整合教程3(异步输出日志)

SpringBoot - 日志框架Log4j2的整合教程3(异步输出日志)

    默认情况下 Log4j2 使用的是同步日志模式。但由于其采用的是 disruptor 高速并发框架,速度很快,因此我们也可以将其改成异步日志模式,提升性能。
Log4j2 支持完全异步模式,也支持异步/同步混合模式,它们性能梯度为:完全异步模式 > 混合模式 > 同步模式

三、异步输出日志

1,准备工作

要启用异步模式的话,除了要引入 Log4j2 依赖外,还需要引入 disruptor 并发框架。
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <!-- 去掉springboot默认配置 -->
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-logging</artifactId>
        </exclusion>
    </exclusions>
</dependency>

<!-- 引入log4j2依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>

<!-- 引入disruptor并发框架 -->
<dependency>
    <groupId>com.lmax</groupId>
    <artifactId>disruptor</artifactId>
    <version>3.4.2</version>
</dependency>

2,完全异步模式

(1)完全异步模式可以最大提升性能,也是官方也比较推荐的模式。一种方法是在启动类中加入相关属性参数(高亮部分)即可:
@SpringBootApplication
public class HanggeTest2Application {

    public static void main(String[] args) {
        //下面语句使得日志输出使用异步处理,减小输出日志对性能的影响
        System.setProperty("Log4jContextSelector",
                "org.apache.logging.log4j.core.async.AsyncLoggerContextSelector");
        SpringApplication.run(HanggeTest2Application.class, args);
    }
}

(2)或者我们也可以在启动参数里设置,下面效果同上面是一样的,按个人喜好选择一种即可:
java -jar -DLog4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector xxx.jar

(3)我们可以通过查看项目启动后的线程名来检查是否真的配置成功了。下面是项目启动后线程情况截图,可以看到有两个线程是关于 Log4j2 的,其中上面红框中的 Log4j2-TF-1-AsyncLogger 就是异步日志输出线程。看到它说明我们的配置是成功的。

3,异步/同步混合模式

(1)如果需要采用混合模式的话,可以通过 log4j2 配置文件中的 Logger 部分进行设置(不需要在启动类或者启动命令中设置参数)。
(2)比如下面配置在前文基础上增加的高亮部分标示:只有该 APP 日志(com.example 包下的代码产生的日志)采用异步模式,其他日志仍然使用同步模式:
<loggers>
    <!--过滤掉spring和mybatis的一些无用的DEBUG信息-->
    <logger name="org.mybatis" level="info" additivity="false">
        <AppenderRef ref="Console"/>
    </logger>
    <!--监控系统信息-->
    <Logger name="org.springframework" level="info" additivity="false">
        <AppenderRef ref="Console"/>
    </Logger>

    <!-- com.example 包下日志采用异步模式 -->
    <AsyncLogger name="com.example" level="info" additivity="false">
        <AppenderRef ref="Console" />
        <AppenderRef ref="Filelog" />
        <AppenderRef ref="RollingFileInfo" />
        <AppenderRef ref="RollingFileWarn" />
        <AppenderRef ref="RollingFileError" />
    </AsyncLogger>

    <root level="info">
        <appender-ref ref="Console"/>
        <appender-ref ref="Filelog"/>
        <appender-ref ref="RollingFileInfo"/>
        <appender-ref ref="RollingFileWarn"/>
        <appender-ref ref="RollingFileError"/>
    </root>
</loggers>

附:异步模式下类方法和行数信息不显示问题解决

1,问题描述

    当我们使用异步模式时,会发现打印的类方法或者行号都无法显示。这是由于默认情况下,异步日志记录器不会将 location 信息传递给 I/O 线程。

2,解决办法

(1)通过设置 includeLocation="true" 可以解决这个问题。设置后 log4j2 将会获取堆栈的快照(snapshot),并遍历堆栈跟踪以查找位置信息。
注重:当然这种方式对性能会有影响,所以如果打印日志的行数和所在方法并非十分必要的话,includeLocation="true" 这个配置能不用尽量不用。

(2)完全异步模式可以如此配置该参数:
<loggers>
    <!--过滤掉spring和mybatis的一些无用的DEBUG信息-->
    <logger name="org.mybatis" level="info" additivity="false">
        <AppenderRef ref="Console"/>
    </logger>
    <!--监控系统信息-->
    <Logger name="org.springframework" level="info" additivity="false">
        <AppenderRef ref="Console"/>
    </Logger>
 
    <root level="info" includeLocation="true">
        <appender-ref ref="Console"/>
        <appender-ref ref="Filelog"/>
        <appender-ref ref="RollingFileInfo"/>
        <appender-ref ref="RollingFileWarn"/>
        <appender-ref ref="RollingFileError"/>
    </root>
</loggers>

(3)混合模式时可以如此配置该参数:
<loggers>
    <!--过滤掉spring和mybatis的一些无用的DEBUG信息-->
    <logger name="org.mybatis" level="info" additivity="false">
        <AppenderRef ref="Console"/>
    </logger>
    <!--监控系统信息-->
    <Logger name="org.springframework" level="info" additivity="false">
        <AppenderRef ref="Console"/>
    </Logger>

    <!-- com.example 包下日志采用异步模式 -->
    <AsyncLogger name="com.example" level="info" additivity="false" includeLocation="true">
        <AppenderRef ref="Console" />
        <AppenderRef ref="Filelog" />
        <AppenderRef ref="RollingFileInfo" />
        <AppenderRef ref="RollingFileWarn" />
        <AppenderRef ref="RollingFileError" />
    </AsyncLogger>

    <root level="info">
        <appender-ref ref="Console"/>
        <appender-ref ref="Filelog"/>
        <appender-ref ref="RollingFileInfo"/>
        <appender-ref ref="RollingFileWarn"/>
        <appender-ref ref="RollingFileError"/>
    </root>
</loggers>

(4)设置后可以看到行数成功显示出来了:
评论0