核心思路是让日志队列满时不卡住业务线程,而是主动丢弃部分日志——丢日志比卡接口更可控;log4j2需配置asyncqueuefullpolicy=discard并调大队列大小,logback需启用neverblock=true和合理discardingthreshold。

核心思路是让日志队列满时不卡住业务线程,而是主动丢弃部分日志——丢日志比卡接口更可控。
Log4j2:改默认阻塞策略为丢弃
Log4j2 默认用 DefaultAsyncQueueFullPolicy,队列满就阻塞业务线程。必须显式改成 DiscardingAsyncQueueFullPolicy:
- 在 log4j2.xml 中配置 AsyncAppender 或 AsyncLogger 时,加上
<discardingasyncqueuefullpolicy></discardingasyncqueuefullpolicy> - 或通过系统属性设置:
-Dlog4j2.AsyncQueueFullPolicy=DiscardingAsyncQueueFullPolicy - 注意:仅启用异步日志(如
<asynclogger></asynclogger>)还不够,不配丢弃策略仍会阻塞
Logback:启用非阻塞写入
Logback 的 AsyncAppender 底层用的是 ArrayBlockingQueue,默认 put() 方法会阻塞。要避免阻塞,需开启 neverBlock:
Java Linux版下载入口,提供 Oracle JDK 26.0.2 官方 Linux 安装包、Java 环境配置、JDBC 数据库连接和 Java 服务端开发相关信息。
- 配置
<neverblock>true</neverblock>,让队列满时调用offer()而非put() - 配合
<discardingthreshold></discardingthreshold>(例如设为队列容量的 80%),提前丢弃低优先级日志(TRACE/DEBUG/INFO) - WARN 及以上级别默认不丢,若也要避免阻塞,必须设
neverBlock="true"
关键参数要调到位
光改策略不够,队列太小照样频繁满:
-
Log4j2 RingBuffer 大小:默认仅 4096,建议设为
log4j2.asyncLoggerRingBufferSize=65536或更高(2 的幂次) -
Logback queueSize:默认 256,压测中至少调到
8192或32768 -
丢弃阈值:Logback 设
discardingThreshold=80表示剩余容量低于 20% 时开始丢 INFO 及以下日志
丢弃不是随便丢,得有兜底和监控
用 DiscardPolicy 不等于放任不管:
- 只对非关键日志(如调试信息、埋点、健康检查)启用丢弃;ERROR 和 WARN 建议保留或降级落盘
- 通过
RejectedExecutionHandler统计被丢弃的日志数,并接入 Prometheus 或告警系统 - 确保磁盘 I/O 瓶颈已排除(如使用 SSD、合理滚动策略),否则再大队列也撑不住
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










