Logback中RollingFileAppender与AsyncAppender日志条目丢失问题求助
嘿,我之前也踩过Logback异步日志丢失的坑,结合你的配置和使用的1.1.10版本来看,大概率是这几个原因导致的,给你整理了排查和修复的方向:
1. 异步Appender压根没被用上
看你的配置,虽然定义了requestQueue、responseQueue这些异步Appender,但你的业务logger(比如abcLogRequest)直接绑定的是同步的abc_req Appender——也就是说,你定义的异步队列完全没起作用。如果你的代码里是通过abcLogRequest这类logger记录日志,那日志都是直接同步写入文件的,这倒不是丢失的直接原因,但如果想借助异步提升性能,得把logger的appender引用改成异步的那个:
<logger name="abcLogRequest" level="INFO" additivity="false"> <appender-ref ref="requestQueue"/> <!-- 替换成异步Appender的名称 --> </logger>
2. 缺少Shutdown Hook导致进程退出时丢日志
这绝对是你日志丢失的核心原因之一!你把DelayingShutdownHook注释掉了,而Logback 1.1.10的AsyncAppender在应用关闭时,不会自动等待队列里的日志刷入磁盘——如果没有shutdown hook,JVM一退出,队列中还没来得及写入的日志就直接丢了。
赶紧把注释去掉,还可以根据你的队列大小调整延迟时间(默认10秒,比如改成15秒确保队列清空):
<shutdownHook class="ch.qos.logback.core.hook.DelayingShutdownHook"> <delay>15000</delay> <!-- 等待15秒,给队列足够的刷盘时间 --> </shutdownHook>
3. 日志目录不存在或权限不足
Logback 1.1.10的RollingFileAppender不会自动创建不存在的父目录,如果${log}/abc/request/这类目录没提前创建,或者应用进程没有读写权限,日志会静默写入失败,看起来就像是“丢失”了。
解决办法:要么手动创建所有需要的日志目录,要么考虑升级到Logback 1.2+版本(新版本支持自动创建目录)。
4. 队列满后的崩溃风险
你把discardingThreshold设为0,这意味着队列满时不会丢弃任何日志,会直接阻塞主线程。如果此时应用因为OOM、强制kill等原因突然崩溃,队列里的日志肯定会丢失。
建议:根据你的峰值流量合理调整queueSize,同时监控队列的使用情况;另外,避免直接用kill -9这类强制终止命令,尽量用正常的 shutdown 流程,让shutdown hook有机会处理队列日志。
5. 时区差异导致日志“躲”到其他文件里
你的滚动日志文件名用了%d{yyyy-MM-dd-HH},默认用的是JVM的时区。如果你的应用时区和你查看日志的时区不一致,可能日志被写到了你没注意的小时文件里,看起来像是丢失了。
可以在日期格式里指定时区,比如统一用UTC:
<fileNamePattern>${log}/abc/request/request.log.%d{yyyy-MM-dd-HH,UTC}</fileNamePattern>
或者检查JVM的时区设置是否符合预期。
最后,建议开启Logback自身的调试模式,帮你排查潜在的配置或写入问题:在<configuration>标签里加上debug="true",这样Logback会输出自身的运行日志,比如是否成功创建Appender、有没有写入错误等:
<configuration debug="true"> <!-- 你的其他配置内容 --> </configuration>
内容的提问来源于stack exchange,提问作者Ashish Malhotra

