Log4j2默认阻塞生产者,可配TimeoutWaitStrategy超时丢弃;Logback默认丢最老日志,丢新日志需扩展实现;两者队列满均反映日志过载,应优化日志量、格式及监控水位。

Log4j2 和 Logback 是 Java 中最常用的日志框架,它们都支持异步日志(通过 AsyncAppender 或 AsyncLogger),底层依赖阻塞队列(如 ArrayBlockingQueue)。当队列满时,行为取决于配置的拒绝策略(DiscardPolicy),默认通常为丢弃新日志(尤其是低优先级日志),但可自定义。
Log4j2 中异步队列满的策略配置
Log4j2 的异步日志主要通过 AsyncLogger(推荐)或 AsyncAppender 实现。队列容量和拒绝策略在 log4j2.xml 或 log4j2.yml 中配置:
-
设置队列大小:通过系统属性
AsyncLogger.RingBufferSize(默认 212 = 4096)控制 RingBuffer 容量(注意:AsyncLogger 使用 LMAX Disruptor 的 RingBuffer,不是普通 BlockingQueue); -
拒绝策略不可直接替换:Disruptor 默认在 RingBuffer 满时阻塞生产者(即日志调用线程等待),但可通过
AsyncLogger.WaitStrategy调整等待行为(如TimeoutWaitStrategy配合超时丢弃); -
启用丢弃策略:添加 JVM 参数
-Dlog4j2.asyncLoggerWaitStrategy=TimeoutWaitStrategy,再配合-Dlog4j2.asyncLoggerRingBufferSize=8192提升缓冲能力; -
更可控的方式:改用
AsyncAppender,它基于ArrayBlockingQueue,支持显式配置BlockingQueue类型及拒绝策略(需自定义 Appender 或使用DiscardingAsyncAppender扩展)。
Logback 中异步队列满的策略配置
Logback 的 AsyncAppender 基于标准 ArrayBlockingQueue,拒绝策略更直观可配:
-
设置队列大小:在
logback.xml中通过<queueSize>256</queueSize>指定(默认 256); -
配置丢弃策略:默认是
DiscardingAsyncAppender行为 —— 队列满时丢弃**最老**日志(FIFO 丢弃); -
切换为丢弃新日志:Logback 本身不内置“丢弃新日志”策略,但可通过继承
AsyncAppender并重写append()方法,在offer()失败时直接 return(即静默丢弃当前日志); -
避免丢失关键日志:对 ERROR 级别日志,建议绕过异步(用同步 Appender),或用
NeverBlock+ 自定义 fallback(例如降级写入本地文件)。
通用建议与避坑点
无论用哪个框架,异步日志队列满本质反映系统日志吞吐已超承载能力,应从根因优化:
立即学习“Java免费学习笔记(深入)”;
- 检查是否过度打印 DEBUG/INFO 日志(尤其循环内、高频接口);
- 评估日志格式是否冗余(如全堆栈、大对象 toString)、是否启用了不必要的上下文(MDC 过大);
- 异步队列不宜盲目调大(如设为 10 万),会掩盖问题且增加 GC 压力和内存占用;
- 生产环境建议开启
includeLocation="false"(禁用行号提取),避免日志线程触发 ClassLoader 锁; - 监控异步队列水位:Log4j2 可通过 JMX 查看
AsyncLogger.RingBuffer的 remainingCapacity;Logback 可通过 MBean 或自定义 Appender 统计丢弃数。
小结:核心配置项速查
Log4j2(AsyncLogger):-Dlog4j2.asyncLoggerRingBufferSize=8192-Dlog4j2.asyncLoggerWaitStrategy=TimeoutWaitStrategy-Dlog4j2.asyncLoggerTimeout=10(单位 ms,超时则丢弃)
Logback(AsyncAppender):<queueSize>512</queueSize><discardingThreshold>0</discardingThreshold>(0 表示满即丢最老,>0 表示保留前 N 条,其余丢最老)
如需丢新日志,需代码扩展。


















