TOP生产环境最近频频发生日志丢失事件,上了三拨人去解决,过了一段时间又出现了,太诡异了!具体现象如下:
1. 有一半的机器日志正常生成,而另一半的机器几乎没有生成日志。
2. 在日志丢失的机器上,所有普通logger配置的日志文件都没有生成,而root logger配置的日志文件却生成了,并且root logger只记录了搜索引擎的日志,其它日志信息一个都没有。
同样的机器,同样的代码,同样的环境,为什么会出现这种问题呢?
要想弄清楚原因,我们还得先来了解JAVA开源世界里的各种日志组件。
一、日志介绍
1. commons-logging
: Apache最早提供的日志门面接口,主要是为了避免程序的代码和具体的实现相耦合。类似于JDBC的API接口,具体的JDBC Driver是由各个数据库提供商来实现的。通过统一接口解耦,不过其内部也实现了一些简单的日志方案。
2. log4j
: 应用最广泛的一种日志解决方案,主要由Appender, Logger, Pattern,
Category等组成,通过log4j.xml或log4j.properties配置文件来实现日志系统的管理和多样化配置。可单独做为日志方案来使
用,也可以配合commons-logging接口来使用,以达到解耦。
3. slf4j
: Simple Logger Facade for
JAVA,是继commons-logging后的又一日志门面接口。与commons-logging的配置加载实现不同,slf4j是通过类加载来感
知实现的。slf4j还有一个比较好的特性是,可以通过占位符{}来实现日志替换,避免了log.isXXXEnabled这种无耐的判断。
4. logback
: log4j作者的又一力作,作为一个通用可靠、快速灵活的日志框架,将作为log4j的替代和slf4j组成新的日志系统的完整实现。官网上称具有极佳的性能,在关键路径上执行速度是log4j的10倍,且内存消耗更少。
下面是各个组件之间的关系图:
二、加载顺序
1. commons-logging
:它是通过LogFactory.getgetFactory()方法按照固定的顺序来加载实现类的:
1) 首先:通过查找系统变量org.apache.commons.logging.LogFactory
的配置值来加载相应的实现(可通过JVM的启动参数来配置)。
2) 否则,扫描ClassPath路径下的META-INF/services/org.apache.commons.logging.LogFactory
文件,通过此文件的第一行配置值来加载实现(jcl-over-slf4j.jar中包含此文件)。
3)否则,从ClassPath中寻找commons-loggings.properties文件,通过里面的配置项org.apache.commons.logging.LogFactory
来加载相应的实现。
4)否则,使用默认的配置方式:如果能找到log4j则默认使用log4j实现,如果没有则使用JDK14Logger
实现,再没有则使用commons-logging内部提供的SimpleLog
实现。
2. slf4j
: 它是通过LoggerFactory类在编译时绑定的import org.slf4j.impl.StaticLoggerBinder
类加载的,任何一种基于slf4j的实现都要有一个这个类。
三、如何使用
1. commons-logging + log4j
这是应用最广泛的日志方案,大部分开源软件都采用了这种方式。使用此方案只需引入commons-logging和log4j两个jar包,并提供log4j.xml或log4j.properties配置文件即可。代码如下:
1) private static final Log log = LogFactory.getLog(LogTest.class); //推荐使用这种方式
2) private static final Logger log = Logger.getLogger(LogTest.class); // 使用这种方式其实只需要引入log4j包即可
2.
slf4j + logback
此方案性能高,使用灵活方便,可使用默认配置文件,也可以通过加载指定的配置文件。使用此方案需要引入slf4j, logback-core和logback-classic三个jar包。代码如下:
private static final Logger logger = LoggerFactory.getLogger(LogTest.class);
3. commons-logging + slf4j + log4j
如果原有的系统中使用的是commons-logging +
log4j,需要迁移到slf4j,则需要使用jcl-over-slf4j桥接包,这个包提供了一个桥接,让底层实现是基于slf4j。使用此方案需要
引入commons-logging, jcl-over-slf4j,
slf4j-log4j和log4j四个jar包。代码和commons-logging + log4j是一样的。
private static final Log log = LogFactory.getLog(LogTest.class)
四、问题诊断
有了上面的了解,现在来回头看一下日志丢失的问题就方便了,你会发现所有的诡异问题背后其实都是有原因的。
首先来看一下TOP生产环境中都依赖了哪些日志jar包:
- commons-logging
- log4j
- slf4j
- logback(包含org.slf4j.impl.StaticLoggerBinder)
- jcl-over-slf4j(包含META-INF/services/org.apache.commons.logging.LogFactory)
- slf4j-log4j(包含org.slf4j.impl.StaticLoggerBinder)
几乎引入了上面提到的所有日志组件,不出问题才怪,现在我们来分析一下原因:
系统中依赖了commons-logging,
jcl-over-slf4j两个包,根据commons-logging的加载顺序可以知道,只要依赖了jcl-over-slf4j包,系统必定被桥
接到了slf4j的日志方案上来。更加杯具的是,系统中有两个org.slf4j.impl.StaticLoggerBinder实现,由于JVM加载
类的随机性,整个系统将会出现两种日志方案:
1) commons-logging + slf4j + logback
2) commons-logging + slf4j + log4j
由于TOP系统是采用log4j.xml来配置的,如果系统采用的是1)方案,则显然没有日志输出;如果采用的是2)方案,则输出正常。这也就解释了为什么会出现“有一半的机器日志正常生成,而另一半的机器几乎没有生成日志”
但还有一个问题无法解释的是:为什么被采用1)方案的机器上还有root.log生成,并且里面只有搜索引擎的日志。细心的同学可以发现上面的“使
用方式”中介绍了可以直接通过log4j的Logger log =
Logger.getLogger(LogTest.class)来使用,果然通过查看搜索引擎的代码发现里面是直接使用了log4j来记日志的,没有采
用commons-logging门面接口,而log4j是认识log4j.xml的,再加上搜索引擎的包路径没有被配置成普通的logger,所以搜索
引擎的日志会被记录在root logger下。这也就解释了什么会出现“普通的logger没有日志生成,而root logger却有日志生成”
五、如何解决
1) 删除jcl-over-slf4j.jar,采用commons-logging + log4j实现
或者
2) 删除logback.jar,采用commons-logging + slf4j + log4j实现
来源:http://rdc.taobao.com/team/top/2011/03/06/java%E6%97%A5%E5%BF%97%E4%B8%A2%E5%A4%B1%E7%BB%88%E6%9E%81%E5%89%96%E6%9E%90/
分享到:
相关推荐
本文将对JAVA日志框架适配中可能出现的冲突进行分析和解决,涵盖日志框架的基本概念、常见的冲突原因和解决方案。 日志框架的基本概念: 在JAVA中,日志框架可以分为两种:日志抽象/门面和日志实现。日志抽象/门面...
`SimpleFormatter`将日志输出为易于阅读的文本格式,而`XMLFormatter`则生成XML格式的日志,更便于解析和分析。 在代码中,我们可以创建`FileHandler`并将其添加到`Logger`实例,以实现自定义的日志输出。下面是一...
Java发送Syslog日志是一种常见的系统日志管理方式,尤其在分布式系统中,它能帮助开发者收集、分析和处理来自不同节点的日志信息。Syslog协议是一个标准的日志消息传递协议,广泛应用于网络设备、操作系统和其他软件...
优点:可分析大日志,大量文件,避免java分析大日志的数据量过大导致的内存泄漏问题。 高效,调用linux shell预筛选,不需加载日志加载的jvm内存。 快速,2-3G的文件可在几十秒内完成筛选,相对java代码分析日志...
Java语言编写的日历日志程序是一个典型的课程设计项目,主要目标是让学生掌握Java编程基础以及实际应用。这个程序提供了日历浏览和日志管理的功能,对于初学者来说,这样的项目能够帮助他们深入理解面向对象编程、...
【Java 日志从入门到实战】Java 日志在软件开发中扮演着至关重要的角色,它不仅帮助程序员在项目开发和维护阶段追踪问题,还能提升系统的可维护性和安全性。本文主要针对Java程序员,深入探讨日志的各个方面,以帮助...
Java自定义日志工具类是Java开发中一个重要的实践,它可以帮助开发者记录应用程序运行过程中的信息,便于调试、排查问题和后期分析。日志工具类通常包含多种级别(如DEBUG, INFO, WARN, ERROR, FATAL)以适应不同...
通过`LogDemo`程序,我们可以了解到在Java中使用`log4j`和`commons-logging`进行日志记录的基本方法,这对于调试、问题排查和性能分析都是至关重要的。在实际开发中,可以根据项目需求调整配置,实现更精细化的日志...
Java提供的如Log4j、SLF4J或Java.util.logging等日志框架,能够帮助开发者对应用程序运行过程中的信息进行详细记录,包括错误、警告、调试信息等,便于后期分析系统性能、定位问题以及优化代码。同时,日志还可以...
Java层次分析法(Analytic Hierarchy Process,AHP)是一种基于多准则决策分析的方法,它通过将复杂问题分解为多个相互关联的子问题,并通过比较和综合这些子问题的相对重要性来解决整个问题。在Java编程环境中实现...
Java日志组件是Java开发中不可或缺的部分,它们用于记录应用程序的运行信息,便于调试、问题定位和性能分析。本文将探讨几个重要的Java日志组件,包括它们之间的关系、如何进行配置以及如何处理与遗留日志框架的兼容...
标题“Java反序列化终极检测工具_Jboss & Weblogic & Websphere.zip”表明这是一个专门用于检测Java应用服务器——Jboss、Weblogic和Websphere中的反序列化漏洞的工具集。这些服务器是企业级Java应用程序的常用平台...
本项目"java开发的基于kafka、xlog的web日志实时分析storm topology"聚焦于使用Java编程语言,结合Kafka消息队列、Xlog日志处理库以及Apache Storm流处理框架,构建了一个能够实时分析Web日志的系统。下面我们将深入...
通过右键选择“用Java打开”,用户可以启动这个分析工具来查看和分析javacore文件。通常,这种工具会提供诸如线程堆栈、内存分配、类加载统计等功能,以便更直观地理解问题所在。 1. **线程堆栈分析**:javacore...
在Java编程中,日志程序是一个非常重要的工具,它用于记录程序运行时的事件、错误信息和其他关键数据,便于后期分析和调试。本教程将详细解释如何使用Java编写一个简单的日志程序,主要涉及以下几个知识点: 1. **...
在分析Java平台安全性时,通常会涉及多个方面,包括但不限于Java虚拟机的安全性、Java类加载器的安全性、Java语言的安全特性、API的安全性以及安全策略等。Java虚拟机的安全性是确保Java代码在执行过程中不会对宿主...
在Java编程领域,决策分析程序通常涉及到数据处理、统计计算以及根据预设规则或算法做出判断和决策。《Java开发典型模块大全》一书中提供的"09决策分析程序"源代码,显然是为了帮助读者理解如何在Java环境中实现这类...
本项目是针对Java平台的日志API统一接口SLF4J的设计源码分析,项目包含361个文件,涵盖263个Java源文件、23个XML配置文件、18个JAR包文件、17个TXT文件、13个HTML文件、9个属性文件、4个YAML文件、4个SLF4J ...