log4j2 2.6+ 默认集成 disruptor,启用异步日志需用 asynclogger 模式(配置 async="true" 或系统属性),排除桥接包干扰,调优 ringbuffer 大小并注意日志丢失与堆栈截断问题。

Java 项目中使用 Log4j2 配合 Disruptor 实现高性能日志,核心在于启用 Log4j2 的异步日志能力——它底层默认就集成了 Disruptor(从 2.6 版本起),无需手动引入 Disruptor 依赖或编写 RingBuffer 相关代码。关键不是“怎么集成 Disruptor”,而是“怎么正确开启并配置 Log4j2 的异步日志模式”。
确认 Log4j2 版本并排除旧日志桥接
Log4j2 自带 Disruptor,但需满足两个前提:
- 使用 Log4j2 2.6 或更高版本(推荐 2.20+,兼容 JDK 8~21,且修复了早期异步日志的内存泄漏等问题);
- 确保项目中没有
log4j-1.2-api或log4j-to-slf4j等桥接包干扰,否则可能退化为同步日志或引发类加载冲突。
检查 Maven 依赖,只保留:
<dependency><groupid>org.apache.logging.log4j</groupid><artifactid>log4j-core</artifactid><version>2.20.0</version></dependency><dependency><groupid>org.apache.logging.log4j</groupid><artifactid>log4j-api</artifactid><version>2.20.0</version></dependency>
启用异步日志的两种方式(推荐 AsyncLogger)
Log4j2 提供两种异步方案:AsyncAppender(包装已有 Appender)和 AsyncLogger(基于 Disruptor 的全局异步,性能更高)。生产环境应优先用后者:
- 在
log4j2.xml或log4j2.json配置文件顶部添加系统属性:<configuration status="WARN" monitorinterval="30"></configuration>—— 并确保 JVM 启动时设置:-Dlog4j2.contextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector - 或者更简单:直接在配置文件根节点加属性
async="true"(Log4j2.17+ 支持):<configuration async="true" status="WARN"></configuration> - Logger 定义无需改动,所有
<logger></logger>或<root></root>自动走 Disruptor 异步路径。
合理配置 Disruptor 参数(避免默认瓶颈)
Disruptor 默认 RingBuffer 大小为 256KB(约 2^16 个事件),在高并发写日志场景下可能成为瓶颈。可通过系统属性调优:
-
-Dlog4j2.asyncLoggerRingBufferSize=131072:设为 128K(2^17),适合每秒万级日志事件; -
-Dlog4j2.enableThreadContextMapInheritable=true:若需传递 MDC/ThreadContext 数据,必须开启(Disruptor 线程不继承主线程上下文); - 避免设置过大的 RingBuffer(如 >1M),会增加 GC 压力,且实际吞吐未必提升。
注意:这些参数仅对 AsyncLogger 生效,AsyncAppender 使用独立队列,需配置 BlockingQueue 容量。
日志输出与异常处理的注意事项
启用 Disruptor 异步后,日志行为有细微变化,需主动适配:
-
日志丢失风险:JVM 快速退出(如调用
System.exit())时,RingBuffer 中未消费的日志会丢失。解决方案:应用关闭前显式调用LogManager.shutdown(); -
异常堆栈截断:默认情况下,异步日志可能省略部分堆栈帧。可在配置中为
PatternLayout显式指定%throwable{full}或%xEx; -
避免在日志参数中做重操作:如
logger.info("user: {}", heavyCompute()),即使异步,heavyCompute()仍在业务线程执行,应改用懒加载形式:logger.info("user: {}", () -> heavyCompute())(Log4j2 2.4+ 支持 Supplier)。
不复杂但容易忽略——关键是选对异步模式、配好 RingBuffer、关掉干扰桥接,剩下的 Disruptor 已由 Log4j2 封装妥当。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











