log4j2异步日志未生效是因为未显式启用异步机制:必须同时引入log4j-core与disruptor(≥3.4.4)依赖,并添加jvm参数-dlog4j2.contextselector=org.apache.logging.log4j.core.async.asyncloggercontextselector,否则asynclogger退化为同步。

Log4j2异步日志为什么没生效?
默认配置下AsyncLogger根本不会启用——它不是开箱即用的“自动加速”,必须显式启用异步机制。常见错误是只配了AsyncLogger标签,却漏掉JVM参数或核心依赖。
- 必须添加
log4j-core和disruptor(≥3.4.4)两个jar,缺一不可;旧版Disruptor会直接静默失败 - 启动时加JVM参数:
-Dlog4j2.contextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector,否则所有AsyncLogger退化为同步 - 别在
log4j2.xml里混用AsyncLogger和AsyncAppender,二者原理不同、不能嵌套,混用会导致日志丢失
按天滚动的日志文件名总不对?
RollingFileAppender的fileName和filePattern不是一回事:前者是当前写入的活跃文件路径,后者才是归档时生成的带日期的文件名模板。很多人把两者写成一样,结果每天只覆盖一个文件,从不归档。
-
fileName应写死,比如logs/app.log,不带日期占位符 -
filePattern必须含%d{yyyy-MM-dd},例如logs/app-%d{yyyy-MM-dd}.%i.log(%i用于解决单日多文件冲突) - 如果用了
TimeBasedTriggeringPolicy但没配DefaultRolloverStrategy,旧日志会被立即删除——加max="30"才能保留30天
异步+滚动组合后CPU飙高或日志延迟?
Disruptor环形缓冲区默认大小是256KB,小缓冲区在高并发打满后会阻塞线程,反而比同步还慢;而大缓冲区又吃内存。这不是配置越“大”越好,得看吞吐量和延迟容忍度。
- 通过JVM参数调缓冲区:
-Dlog4j2.asyncLoggerRingBufferSize=1024(推荐512~4096,2的幂次) - 避免在日志里拼接大量字符串,比如
logger.info("user="+user.toString()+" action="+action)——异步模式下这会在调用线程执行,白费异步 - 检查是否启用了
includeLocation="true",它会触发堆栈遍历,在异步场景下开销翻倍,非调试期建议关掉
Spring Boot项目里log4j2.xml不加载?
Spring Boot 2.4+默认禁用XML配置自动发现,即使你放对了位置,它也会安静地忽略log4j2.xml,转而用默认的Logback。
立即学习“Java免费学习笔记(深入)”;
- 确保
spring-boot-starter-log4j2已替换掉spring-boot-starter-logging,且无其他日志框架jar残留 - 在
application.properties中强制指定:logging.config=classpath:log4j2.xml - XML文件必须放在
src/main/resources根目录,不能套在子文件夹里;名字必须是log4j2.xml,log4j2-spring.xml在某些Boot版本中不被识别
最常被跳过的其实是Disruptor版本与Log4j2主版本的匹配关系——比如Log4j2 2.17要求Disruptor ≥3.4.4,但Maven传递依赖可能拉来3.3.4,表面能跑,实则异步失效。真要确认是否生效,看应用启动日志里有没有Using Disruptor version这一行。











