logback通过asyncappender包装同步appender实现异步日志,其核心是将日志事件提交至后台队列由独立线程消费;需先定义同步appender(如rollingfileappender),再用asyncappender引用,并绑定到root或指定logger。

Logback 本身不直接提供异步日志的 <appender></appender> 标签,而是通过 AsyncAppender 包装同步 Appender 来实现异步写入。核心思路是:把日志事件提交给一个后台线程队列,由独立线程消费并委托给目标 Appender(如 FileAppender、ConsoleAppender)处理。
配置 AsyncAppender 包裹目标 Appender
AsyncAppender 是一个“装饰器”型 Appender,它不负责实际输出,只负责异步调度。你需要先定义一个同步 Appender(比如输出到文件),再用 AsyncAppender 引用它:
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logs/app.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>logs/app.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>10MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<p><!-- 异步包装 -->
<appender name="ASYNC_FILE" class="ch.qos.logback.classic.AsyncAppender">
<appender-ref ref="FILE"/>
<!-- 可选:队列大小,默认256 -->
<queueSize>1024</queueSize>
<!-- 可选:丢弃超过队列容量的日志?默认true -->
<discardingThreshold>0</discardingThreshold>
<!-- 可选:是否包含调用者信息(如行号),异步下默认false以提升性能 -->
<includeCallerData>false</includeCallerData>
</appender>将 AsyncAppender 绑定到 Logger 或 root
配置好 AsyncAppender 后,需将其关联到 logger,才能生效:
- 绑定到 root logger(全局生效):
<root level="INFO"> <appender-ref ref="ASYNC_FILE"/> </root>
- 或指定某个包/类使用异步日志:
<logger name="com.example.service" level="DEBUG" additivity="false"> <appender-ref ref="ASYNC_FILE"/> </logger>
关键参数说明与调优建议
AsyncAppender 的行为受几个关键参数影响,合理设置可避免丢日志或内存溢出:
- queueSize:阻塞队列容量。默认 256,建议根据吞吐量设为 512–4096;过小易丢日志,过大占内存
- discardingThreshold:当队列剩余容量 ≤ 该值时,新日志会被丢弃(非 ERROR 级别)。设为 0 表示队满即丢;设为 queueSize 则永不丢(但可能阻塞)
- includeCallerData:若需 %class、%method、%line 等信息,需设为 true,但会显著降低性能(需遍历栈帧),异步场景通常关闭
- neverBlock:设为 true 时,队列满则直接丢日志(不等待);默认 false(会阻塞生产者线程直到有空位)
注意事项与常见问题
AsyncAppender 虽提升性能,但引入了新约束:
- 日志输出不保证实时可见:异步线程可能延迟写入,程序崩溃时队列中日志会丢失
- 异常堆栈在异步模式下可能不完整:除非开启
includeCallerData且日志级别含 ERROR,否则不会自动补全 - 不要对 AsyncAppender 嵌套使用:即不能让一个 AsyncAppender 引用另一个 AsyncAppender
- 如果同时需要控制台和文件异步输出,应分别定义两个 AsyncAppender,各自包装 ConsoleAppender 和 RollingFileAppender









