Spring Boot 3.x 整合 Logback 日志框架(支持异步写入)
在构建任何应用程序时,良好的日志管理都是必不可少的。日志可以帮助我们监控、调试和跟踪代码的运行情况。
1. 添加日志配置文件
在 /resources
资源目录下,创建名为 logback-spring.xml
日志配置文件:
文件内容如下:
xml
<configuration>
<!-- 引用 Spring Boot 的 logback 基础配置 -->
<include resource="org/springframework/boot/logging/logback/defaults.xml" />
<!-- 应用名称 -->
<property scope="context" name="appName" value="auth"/>
<!-- 自定义日志输出路径,以及日志名称前缀 -->
<property name="LOG_FILE" value="./logs/${appName}.%d{yyyy-MM-dd}"/>
<!-- 每行日志输出的格式 -->
<property name="LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n"/>
<!-- 文件输出 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- 日志文件的命名格式 -->
<fileNamePattern>${LOG_FILE}-%i.log</fileNamePattern>
<!-- 保留 30 天的日志文件 -->
<maxHistory>30</maxHistory>
<!-- 单个日志文件最大大小 -->
<maxFileSize>10MB</maxFileSize>
<!-- 日志文件的总大小,0 表示不限制 -->
<totalSizeCap>0</totalSizeCap>
<!-- 重启服务时,是否清除历史日志,不推荐清理 -->
<cleanHistoryOnStart>false</cleanHistoryOnStart>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${LOG_PATTERN}</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<!-- 本地 dev 开发环境 -->
<springProfile name="dev">
<include resource="org/springframework/boot/logging/logback/console-appender.xml" />
<root level="INFO">
<appender-ref ref="CONSOLE"/> <!-- 输出控制台日志 -->
<appender-ref ref="FILE"/> <!-- 打印日志到文件中。PS: 本地环境下,如果不想打印日志到文件,可注释掉此行 -->
</root>
</springProfile>
<!-- 其它环境 -->
<springProfile name="prod">
<include resource="org/springframework/boot/logging/logback/console-appender.xml" />
<root level="INFO">
<appender-ref ref="FILE"/> <!-- 生产环境下,仅打印日志到文件中 -->
</root>
</springProfile>
</configuration>
说一下日志配置文件中,每项配置都是干啥的:
- 基础配置和属性定义:
makefile
<include resource="org/springframework/boot/logging/logback/defaults.xml" />
上述配置用于引用 Spring Boot 的默认 Logback 基础配置。
perl
<property scope="context" name="appName" value="auth"/>
<property name="LOG_FILE" value="./logs/${appName}.%d{yyyy-MM-dd}"/>
<property name="LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n"/>
- 定义了一些全局属性:
appName
:应用名称,这里值填写为auth
,表示认证服务。LOG_FILE
:日志文件的路径和文件名模板,./logs
表示输出到项目的同级目录下的/logs
文件夹下。LOG_PATTERN
:日志输出格式。
- 日志文件 Appender 配置:
php-template
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_FILE}-%i.log</fileNamePattern>
<maxHistory>30</maxHistory>
<maxFileSize>10MB</maxFileSize>
<totalSizeCap>0</totalSizeCap>
<cleanHistoryOnStart>false</cleanHistoryOnStart>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${LOG_PATTERN}</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
appender
:用于将日志输出到文件,并且使用滚动策略来管理日志文件。rollingPolicy
:定义了日志滚动策略,使用SizeAndTimeBasedRollingPolicy
以时间和大小为基准进行滚动。fileNamePattern
:定义了日志文件的命名模式。maxHistory
:保留 30 天的日志文件。maxFileSize
:每个日志文件最大 10MB。totalSizeCap
:总日志文件大小没有限制。cleanHistoryOnStart
:项目启动时不清理历史日志文件。encoder
:定义了日志的输出格式,以及文件编码格式。- Spring Profile 配置 :用于配置各环境的日志行为。这里主要定义了
dev
和prod
两个环境:
php-template
<springProfile name="dev">
<include resource="org/springframework/boot/logging/logback/console-appender.xml" />
<root level="INFO">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
</root>
</springProfile>
dev
本地开发环境中,包含控制台输出 CONSOLE
和文件输出 FILE
。CONSOLE
配置通过包含 Spring Boot 默认的 console-appender.xml
实现。
php-template
<springProfile name="prod">
<include resource="org/springframework/boot/logging/logback/console-appender.xml" />
<root level="INFO">
<appender-ref ref="FILE"/>
</root>
</springProfile>
prod
生产环境中,仅包含文件输出 FILE
,不输出到控制台。这是为了生产环境中减少控制台日志输出,避免影响性能。
拓展小知识 : 如果你想同时设置多个环境,假设咱们除了本地开发环境、生产环境外,还有个
test
测试环境, 也仅需要输出日志到文件。则可以配置如下,通过逗号,
分隔开来就行:
php-template<springProfile name="test,prod"> // 省略... </springProfile>
2. 异步日志
异步打印日志(Asynchronous Logging)是一种日志记录方式,它将日志写入操作放在一个单独的线程中执行,而不是在主线程中进行。这意味着日志写入的过程不会阻塞主线程的执行,主线程可以继续执行其余的业务逻辑,增强了应用的性能和响应速度。
2.1 为什么需要异步打印日志
- 性能提升:同步日志记录在高并发情况下会显著影响应用性能,因为每一次日志写入操作都可能导致磁盘 I/O 操作,主线程必须等待这些操作完成才能继续执行。异步日志记录将这些操作放在单独的线程中进行,避免了主线程的阻塞,提高了整体性能。
- 响应时间:异步日志记录可以减少应用的响应时间,尤其是在需要记录大量日志信息的时候。用户请求得到快速响应,而日志记录在后台处理。
- 资源利用:通过异步日志记录,应用可以更有效地利用 CPU 资源。同步日志记录可能导致线程频繁等待 I/O 操作完成,而异步记录可以让这些线程去执行其他任务,提高资源利用率。
- 系统稳定性:在极端情况下(例如,日志量非常大时),同步日志记录可能会导致应用出现性能瓶颈甚至崩溃。异步日志记录通过缓冲和队列机制,能够更好地应对突发的大量日志请求,增强系统稳定性。
2.2 Logback 配置异步日志
Logback 提供了 AsyncAppender
来支持异步日志记录。通过 AsyncAppender
可以将日志事件发送到一个队列中,并由一个独立的线程池来处理这些日志事件。编辑 logback-spring.xml
文件,添加配置如下:
php-template
// 省略...
<!-- 文件输出 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
// 省略...
</appender>
<!-- 异步写入日志,提升性能 -->
<appender name="ASYNC_FILE" class="ch.qos.logback.classic.AsyncAppender">
<!-- 是否丢弃日志, 0 表示不丢弃。默认情况下,如果队列满 80%, 会丢弃 TRACE、DEBUG、INFO 级别的日志 -->
<discardingThreshold>0</discardingThreshold>
<!-- 队列大小。默认值为 256 -->
<queueSize>256</queueSize>
<appender-ref ref="FILE"/>
</appender>
<!-- 本地 dev 开发环境 -->
<springProfile name="dev">
<include resource="org/springframework/boot/logging/logback/console-appender.xml" />
<root level="INFO">
<appender-ref ref="CONSOLE"/> <!-- 输出控制台日志 -->
<appender-ref ref="ASYNC_FILE"/> <!-- 打印日志到文件中。PS: 本地环境下,如果不想打印日志到文件,可注释掉此行 -->
</root>
</springProfile>
<!-- 其它环境 -->
<springProfile name="prod">
<include resource="org/springframework/boot/logging/logback/console-appender.xml" />
<root level="INFO">
<appender-ref ref="ASYNC_FILE"/> <!-- 生产环境下,仅打印日志到文件中 -->
</root>
</springProfile>
// 省略...
解释一下修改的地方,主要添加了一个名称为
ASYNC_FILE
异步输出日志的Appender
:
AsyncAppender
使用内部队列来异步处理日志事件。queueSize
:队列的大小。discardingThreshold
:是否丢弃日志, 0 表示不丢弃。最后,将各个环境中的
FILE
更改为ASYNC_FILE
异步写入日志。别忘了,再次重启一下项目,自测一波日志功能是否好使~