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)设置后可以看到行数成功显示出来了: