关于DailyRollingFileAppender滚动时生成双活跃日志文件的问题咨询
日志滚动双文件活跃写入问题分析与解决
我来帮你捋清楚这个问题,我之前也碰到过类似的情况,咱们一步步来拆解:
问题根源
你用的DailyRollingFileAppender和AsyncAppender组合存在经典的线程安全隐患:
- 触发日志滚动(到新日期)时,
DailyRollingFileAppender会把当前的performance.log重命名为带日期的文件,再创建新的performance.log写入新日志。 - 但
AsyncAppender是异步处理日志的,它的队列里可能还积压着滚动前的日志事件,这些事件持有的还是旧文件的句柄,所以会继续往重命名后的旧文件(比如performance.log.2020.06.08.log)写,同时新日志又写入新的performance.log,最终导致两个文件都处于活跃状态。 - 另外,
DailyRollingFileAppender本身在多线程/异步场景下的文件句柄管理就有已知缺陷,官方也不推荐在这类场景下使用它。
解决方案
方案1:替换为更可靠的滚动策略(推荐)
改用RollingFileAppender配合TimeBasedRollingPolicy(需要引入Apache官方为log4j 1.x提供的log4j-extras扩展包),这个组合的线程安全性更好,能从根源避免文件句柄泄漏问题。
修改后的配置示例:
<appender name="PERFLOG" class="org.apache.log4j.RollingFileAppender"> <!-- 基础日志文件路径 --> <param name="File" value="/wsapps/mpi/deployment/logs/performance.log" /> <!-- 开启追加模式 --> <param name="Append" value="true" /> <!-- 基于时间的滚动策略 --> <rollingPolicy class="org.apache.log4j.rolling.TimeBasedRollingPolicy"> <!-- 滚动后的日志文件名格式 --> <param name="FileNamePattern" value="/wsapps/mpi/deployment/logs/performance.%d{yyyy-MM-dd}.log" /> </rollingPolicy> <!-- 日志格式保持不变 --> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%d|%t|%x|%m%n" /> </layout> </appender> <appender name="ASYNCPERF" class="org.apache.log4j.AsyncAppender"> <appender-ref ref="PERFLOG" /> <!-- 可选:设置队列大小,防止高并发下日志溢出 --> <param name="BufferSize" value="1024" /> </appender>
方案2:调整AsyncAppender配置(治标不治本)
如果暂时不想更换滚动策略,可以尝试调整AsyncAppender参数减少队列积压:
- 设置
<param name="Blocking" value="true" />:当队列满时,让写入线程阻塞,直到队列有空间,避免日志事件积压过多。 - 适当调大
BufferSize:但这只能缓解,无法从根本上解决文件句柄问题。
方案3:升级到Log4j 2.x(长远最优解)
Log4j 1.x已经停止维护多年,Log4j 2.x重新设计了异步日志和滚动机制,性能与稳定性大幅提升,完全避免了旧版本的这类缺陷。如果项目允许,建议直接升级到Log4j 2.x,一劳永逸解决问题。
内容的提问来源于stack exchange,提问作者lakshmidivy
相关产品推荐
相关产品推荐

