一、背景:后台有很多任务,每个任务都是一个main函数(JVM或进程),但是所有的任务都加载同一个log4j.xml文件,即往同一份文件中输出日志。

二、原因追踪

在 log4j 的 DailyRollingFileAppender 类中:

Java代码  
  1. void rollOver() throws IOException {
  2. /* Compute filename, but only if datePattern is specified */
  3. if (datePattern == null) {
  4. errorHandler.error("Missing DatePattern option in rollOver().");
  5. return;
  6. }
  7. String datedFilename = fileName+sdf.format(now);
  8. // It is too early to roll over because we are still within the
  9. // bounds of the current interval. Rollover will occur once the
  10. // next interval is reached.
  11. if (scheduledFilename.equals(datedFilename)) {
  12. return;
  13. }
  14. // close current file, and rename it to datedFilename
  15. this.closeFile();
  16. File target  = new File(scheduledFilename);
  17. if (target.exists()) {
  18. target.delete();
  19. }
  20. File file = new File(fileName);
  21. boolean result = file.renameTo(target);
  22. if(result) {
  23. LogLog.debug(fileName +" -> "+ scheduledFilename);
  24. } else {
  25. LogLog.error("Failed to rename ["+fileName+"] to ["+scheduledFilename+"].");
  26. }
  27. try {
  28. // This will also close the file. This is OK since multiple
  29. // close operations are safe.
  30. this.setFile(fileName, false, this.bufferedIO, this.bufferSize);
  31. }
  32. catch(IOException e) {
  33. errorHandler.error("setFile("+fileName+", false) call failed.");
  34. }
  35. scheduledFilename = datedFilename;
  36. }

该方法的作用是:在滚动备份时间间隔到的时刻,将前一时间间隔的日志备份,同时以非追加模式将新日志打到新日志文件中;

中间部分代码意思是:如果备份文件不存在,则备份,同时创建新日志文件;如果存在,则先删除掉,再备份;

好,问题在这个时刻就出现了:(假设A进程先进行滚动备份)

1、对于A进程:
a. 先将project.log备份(renameTo())为project.log.2009.08.18,然后创建project.log文件,并将日志写在project.log中;
b. 此时A进程持有project.log的文件句柄;而B进程仍然持有project.log.2009.08.18的文件句柄(尽管被重命名,但句柄不变);

2、对于B进程:发现以project.log.2009.08.18为文件名的文件已经存在,则将其删除(前一时间段的所有日志全没了),并将以project.log为文件名的文件重命名为project.log.2009.08.18,然后创建project.log文件;

3、此时A进程持有project.log.2009.08.18的文件句柄(被B进程重命名过的),而B进程持有最新创建的project.log;

4、结果导致:前一时间段日志丢失,A、B进程在不同的文件里打日志;

三、解决方案

1、改变 rollOver() 方法的实现方式:定义 TaskDailyRollingFileAppender 类,该类继承至 FileAppender ,它与 DailyRollingFileAppender 的主要区别在于以下方法:

Java代码  
  1. void rollOver() throws IOException {
  2. /* Compute filename, but only if datePattern is specified */
  3. if (datePattern == null) {
  4. errorHandler.error("Missing DatePattern option in rollOver().");
  5. return;
  6. }
  7. String datedFilename = fileName+sdf.format(now);
  8. // It is too early to roll over because we are still within the
  9. // bounds of the current interval. Rollover will occur once the
  10. // next interval is reached.
  11. if (scheduledFilename.equals(datedFilename)) {
  12. return;
  13. }
  14. // close current file, and rename it to datedFilename
  15. this.closeFile();
  16. File target  = new File(scheduledFilename);
  17. if (!target.exists()) {
  18. File file = new File(fileName);
  19. boolean result = file.renameTo(target);
  20. if (result) {
  21. LogLog.debug(fileName + " -> " + scheduledFilename);
  22. } else {
  23. LogLog.error("Failed to rename [" + fileName + "] to [" + scheduledFilename + "].");
  24. }
  25. }
  26. try {
  27. // This will also close the file. This is OK since multiple
  28. // close operations are safe.
  29. this.setFile(fileName, true, this.bufferedIO, this.bufferSize);
  30. }
  31. catch(IOException e) {
  32. errorHandler.error("setFile("+fileName+", false) call failed.");
  33. }
  34. scheduledFilename = datedFilename;
  35. }

改进后的 rollOver() 方法主要作用是:A进程先将日志重命名,然后创建新日志文件,B进程发现已经存在,则直接以追加模式切换到新的日志文件上去;

2、如果是任务,根据启动参数taskName 属性区分日志文件:

a. 目前所有后台任务在启动脚本里都加上了 -DtaskName 属性;
b. 定义 TaskDailyRollingFileAppender 类,该类继承 DailyRollingFileAppender,并覆盖其 setFile(String file) 方法:

Java代码  
  1. public void setFile(String file) {
  2. String taskName = System.getProperty("taskName");
  3. if (!StringUtil.isEmpty(taskName)) {
  4. file = file + "." + taskName;
  5. }
  6. super.setFile(file);
  7. }

c. 这样实现后,对于不同的任务,日志文件名会以.taskName结尾,对于没有指定 taskName 的任务,不受影响;

多进程log4j日志丢失问题分析相关推荐

  1. python多进程log日志问题_Python 如何安全地实现实现多进程日志以及日志正常的分割...

    在Python中我们经常需要使用到多进程来提高我们程序性能,但是多进程的编程中经常有各种各样的问题来困扰我们,比如多进程和多线程的公用导致的子进程的卡死,进程间的通信等问题.还有一个问题我们也许不经常 ...

  2. python logging模块的作用_Python 日志模块logging分析及使用-2

    本文作为Python日志模块的补充,主要介绍日志回滚RotatingFileHandler和TimedRotatingFileHandler的使用,以及其所带来的问题.Logger对象的日志等级是如何 ...

  3. Hibernate Log4j日志记录

    Hibernate Log4j日志记录 欢迎来到Hibernate Log4j Logging示例.Hibernate 4在旧的hibernate版本中使用JBoss日志而不是slf4j.今天我们将研 ...

  4. 下载丨9月数据库技术通讯:Redo日志丢失,重建遭遇ORA-16433处理

    为了及时共享行业案例,通知共性问题,达成共享和提前预防,我们整理和编辑了<云和恩墨技术通讯>,通过对过去一段时间的知识回顾,故障归纳,以期提供有价值的信息供大家参考.同时,我们也希望能够将 ...

  5. log4j日志输出性能优化-缓存、异步

    1.log4j已成为大型系统必不可少的一部分,log4j可以很方便的帮助我们在程序的任何位置输出所要打印的信息,便于我们对系统在调试阶段和正式运行阶段对问题分析和定位.由于日志级别的不同,对系统的性能 ...

  6. 【ELK】ELK菜鸟手记 (一) 环境配置+log4j日志记录——转自Master HaKu

    感谢Master HaKu的分享,博客园的账号忘了,文章里面有原文链接,尊重原创 ELK菜鸟手记 (一) 环境配置+log4j日志记录 - Master HaKu - 博客园 Master HaKu ...

  7. Spring、Mybatis整合Service优化思路,DAO层、Service层最终编码以及log4j日志的使用

    5. Spring.Mybatis整合Service层事务控制优化思路分析 # spring中处理事务的两种方式1. 编程式事务处理定义:通过在业务层中注入事务管理器对象,然后通过编码的方式进行事务控 ...

  8. Log4j日志配置详解(Log4j2)

    Log4j日志配置详解 一.Log4j升级Log4j2 首先来说一下日志升级,log4j配置的变化,配置文件从log4j.xml变成了log4j2.xml,配置文件的内容也有很大不同,log file ...

  9. tp5记录用户的操作日志_【干货】日志管理与分析(四)日志管理规程

    接<日志管理与分析(三)--对日志系统的攻击>,如果你的企业没有认真地对待日志,那么就可以说明你的企业对IT可审核性并不重视,这也就是日志记录成为一种完善的依从性技术,许多法规和法律以及最 ...

最新文章

  1. 解决Neither the JAVA_HOME nor the JRE_HOME environment variable is defined问题
  2. 【ASP.NET Core】解决“The required antiforgery cookie xxx is not present”的错误
  3. 怎么把项目推到gitlab上_将本地项目添加到 GitLab 上管理
  4. 如何用C语言编写wav读取函数,C++读取WAV音频文件的头部数据的实现方法
  5. linux 虚拟机同步时间
  6. 在Nginx上配置ThinkPHP项目
  7. docker安装mysql5.6,安装redis3.2
  8. 小米3Android密码怎么解吗,小米路由器3管理密码忘记了怎么办?
  9. AndroidStudio_android中实现ImageView的清空操作---Android原生开发工作笔记235
  10. RocketMQ 集群部署模式 理论介绍
  11. 千万IOPS背后,宏杉科技“MS7000G2-Mach”为金融核心业务赋能
  12. 联想服务器rd640性能,联想RD640服务器产品规格
  13. vivado下载地址和ISE下载地址
  14. Lua EmmyLua 注解详解
  15. Sklearn提供的常用数据集
  16. 微信小程序 短信验证码
  17. mybatis(狂神说笔记)
  18. 中国浓咖啡行业市场供需与战略研究报告
  19. postman数据保存在哪里_Postman教程——使用数据文件
  20. 排球分组循环交叉编排_第九届“理工杯”学生排球比赛正式拉开帷幕

热门文章

  1. cdrx8如何批量导出jpg_CDR怎么批量导出图片
  2. 是什么门的缩写_开车:和她结婚需要注意什么
  3. 全球与中国PMN-PT压电单晶市场深度研究分析报告
  4. 怎么复制黑苹果config配置_黑苹果主机(百分百成功硬件配置)
  5. 110道 Elasticsearch面试题及答案(持续更新)
  6. SQL求用户的最大连续登陆天数
  7. lopa分析_什么是LOPA分析?
  8. 机器学习中的梯度消失问题vanishing gradient
  9. 小学计算机室行事周历,关于小学信息技术教案八篇
  10. Android重写ImageView实现图片镜像效果