log4j2的性能与log4j1相比

时间:2016-09-28 09:30:58

标签: java log4j log4j2

我正在尝试将我的应用迁移到使用log4j2。它目前使用的是log4j 1.2.16。我的项目也有性能构建,升级到log4j 2后,性能似乎有了很大提高。

也就是说,直到我读到有关桥接的内容。根据文档,我必须从类路径中排除log4j1 JAR,并包括桥接JAR - 我假设它被命名为'org.apache.logging.log4j:log4j-1.2-api'。一旦我这样做,性能再次下降。

总结一下:

  1. 性能与log4j2 +桥接jar + log4j-1.2-api + log4j1:好
  2. 使用log4j2 +桥接jar + log4j-1.2-api的性能:糟糕(恢复到log4j1的性能)
  3. 我已经检查过log4j-1.2-api是否在类路径中较早。所以应该先加载它。

    知道什么可能导致这个问题吗?

    非常感谢你!

    哦,我的完整日志记录是:

    • org.slf4j:SLF4J-API
    • org.slf4j:log4j的-过SLF4J
    • org.slf4j:JCL-过SLF4J
    • org.apache.logging.log4j:log4j的-SLF4J-IMPL
    • org.apache.logging.log4j:log4j的核
    • org.apache.logging.log4j:log4j的-API
    • org.apache.logging.log4j:log4j的-1.2-API
    • log4j:log4j(带& without,如上所述)

    版本:

    • Log4j2:2.6.2
    • slf4j:1.7.20
    • log4j1:1.2.16

    我的配置文件如下:

    <?xml version="1.0" encoding="UTF-8"?>
    <Configuration
            xmlns:xi="http://www.w3.org/2001/XInclude">
    
        <xi:include href="log4j2-xinclude-appenders.xml" />
    
        <Loggers>
    
            <Root level="info">
                <AppenderRef ref="rollingFileAppender"/>
                <AppenderRef ref="stdOutAppender"/>
            </Root>
        </Loggers>
    </Configuration>
    

    log4j2-xinclude-appenders.xml如下所示:

    <?xml version="1.0" encoding="UTF-8"?>
    <appenders>
        <RollingRandomAccessFile name="_rollingFileAppender" fileName="./logs/foo-${sys:app.name.suffix}.log"
                     filePattern="./logs/foo-${sys:foo.app.name.suffix}.log.%i">
            <PatternLayout>
                <Pattern>%d|%X{active.profiles}| %-5p |%X{fcp.session}|%X{StateMachine.key}|%X{StateMachine.currentState}| %m | %t | %c{1.}%n</Pattern>
            </PatternLayout>
            <Policies>
                <OnStartupTriggeringPolicy minSize="0" />
                <SizeBasedTriggeringPolicy size="100 MB" />
            </Policies>
            <DefaultRolloverStrategy max="10"/>
        </RollingRandomAccessFile>
    
        <Async name="rollingFileAppender" blocking="false" bufferSize="10000">
            <AppenderRef ref="_rollingFileAppender"/>
        </Async>
    
        <Console  name="_stdOutAppender" target="SYSTEM_OUT">
            <PatternLayout pattern="%d|%X{active.profiles}| %-5p |%X{fcp.session}|%X{StateMachine.key}|%X{StateMachine.currentState}| %m | %t | %c{1.}%n"/>
        </Console>     
        <Async name="stdOutAppender" blocking="false" bufferSize="10000">
            <AppenderRef ref="_stdOutAppender"/>
        </Async>
    </appenders>
    

    编辑:这是包含在类路径中的log4j 1 xml文件

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
    
    <log4j:configuration debug="false" xmlns:log4j="http://jakarta.apache.org/log4j/">
    
        <appender name="A1" class="org.apache.log4j.ConsoleAppender">
            <layout class="org.apache.log4j.PatternLayout">
                <param name="ConversionPattern" value="%d [%t] %-5p %c - %m%n"/>
            </layout>
        </appender>
    
        <appender name="R" class="com.bar.common.util.RollingFileAppender">
            <param name="File" value="./logs/bar.log"/>
            <param name="MaxFileSize" value="100MB"/>
            <param name="MaxBackupIndex" value="10"/>
            <layout class="org.apache.log4j.PatternLayout">
                <param name="ConversionPattern" value="%d [%t] %-5p %c - %m%n"/>
            </layout>
        </appender>
    
        <!-- Performance Appender -->
        <appender name="OneSecondStatsAppender"
                  class="com.foo.perf.AggregatedStatisticsAppender">
            <param name="TimeSlice" value="1000"/>
            <appender-ref ref="OneSecondStatsLogger"/>
        </appender>
        <appender name="FiveMinuteStatsAppender"
                  class="com.bar.perf.DatafabricAggregatedStatisticsAppender">
            <param name="TimeSlice" value="300000"/>
            <appender-ref ref="FiveMinuteStatsLogger"/>
        </appender>
    
        <!-- Aggregated Performance Statistics Appender -->
        <appender name="OneSecondStatsLogger" class="org.apache.log4j.FileAppender">
            <param name="File" value="./logs/bar-performance.log"/>
            <layout class="com.bar.perf.AggregatedStatisticsCsvLayout"/>
            <filter class="com.bar.perf.CategorisedStatisticExclusionFilter"/>
        </appender>
        <appender name="FiveMinuteStatsLogger" class="org.apache.log4j.FileAppender">
            <param name="File" value="./logs/bar-minutes.log"/>
            <layout class="com.bar.perf.AggregatedStatisticsCsvLayout">
                <param name="ShowEmptyStatistics" value="true"/>
            </layout>
        </appender>
    
        <!-- Loggers -->
        <logger name="org.perf4j.TimingLogger" additivity="false">
            <level value="INFO"/>
            <appender-ref ref="OneSecondStatsAppender"/>
            <appender-ref ref="FiveMinuteStatsAppender"/>
        </logger>
    
        <logger name="com.bar">
            <level value="INFO"/>
        </logger>
    
        <logger name="com.gemstone.gemfire">
            <level value="INFO"/>
        </logger>
    
        <logger name="org.springframework.data">
            <level value="INFO"/>
        </logger>
    
        <!-- Root logger configuration -->
        <root>
            <priority value="INFO"/>
            <appender-ref ref="R"/>
        </root>
    
    </log4j:configuration>
    

    编辑2 : 性能不佳的类路径顺序:

    log4j-1.2-api-2.6.2.jar
    jcl-over-slf4j-1.7.20.jar
    slf4j-api-1.7.20.jar
    log4j-slf4j-impl-2.6.2.jar
    log4j-core-2.6.2.jar
    log4j-api-2.6.2.jar
    log4j-1.2.16.jar
    

    良好性能的类路径顺序

    log4j-1.2-api-2.6.2.jar
    jcl-over-slf4j-1.7.20.jar
    slf4j-api-1.7.20.jar
    log4j-over-slf4j-1.7.20.jar
    log4j-slf4j-impl-2.6.2.jar
    log4j-core-2.6.2.jar
    log4j-api-2.6.2.jar
    log4j-1.2.16.jar
    

2 个答案:

答案 0 :(得分:0)

我在这里有两个问题:

  1. 为什么log4j 1在某些类路径配置中使用
  2. 为什么log4j 2不比log4j 1快
  3. <强> 1。为什么使用log4j 1

    我怀疑以下slf4j依赖项导致使用旧的log4j 1.2:

    org.slf4j:log4j-over-slf4j
    org.slf4j:jcl-over-slf4j
    

    如果您使用maven,即使您没有在POM中明确声明,也可以将旧的Log4j 1作为传递依赖项。

    请删除这些。 Log4j 2具有log4j-slf4j-impl和log4j-jcl模块,它们将完成相同的操作,但使用Log4j 2代替。

    你不应该在类路径中有Log4j 1。如果您的应用程序(或您使用的任何库)依赖于Log4j 1 API,则添加log4j-1.2-api模块。

    <强> 2。为什么log4j 2不比log4j 1快

    您描述的配置没有利用log4j 2功能。它使用AsyncAppender(在log4j 1和2中大致相当)和ConsoleAppender(在log4j 2中略差)。 ConsoleAppender is about 60 times slower比文件appender。在生产系统中登录控制台时要格外小心。

    以下是我的建议:删除以下内容(现在似乎可以提供更好的效果,但请耐心等待)

    • 的log4j-过SLF4J-1.7.20
    • 的log4j-1.2.16
    • 旧的lo4j.xml配置

    添加 LMAX Disruptor依赖项:

    <!-- https://mvnrepository.com/artifact/com.lmax/disruptor -->
    <dependency>
        <groupId>com.lmax</groupId>
        <artifactId>disruptor</artifactId>
        <version>3.2.0</version>
    </dependency>
    

    使用以下log4j2.xml配置。暂时只是把它变成一个没有包含的简单文件,你可以稍后再把它放回去。 (注意我将<Configuration status="trace"添加到文件的开头:这将输出内部log4j2调试语句,这样您就可以确认配置完成没有问题。)

    请注意,由于我怀疑它会影响性能,因此我将控制台记录WARN级别。

    <?xml version="1.0" encoding="UTF-8"?>
    <Configuration status="TRACE" xmlns:xi="http://www.w3.org/2001/XInclude">
    
      <appenders>
        <RollingRandomAccessFile name="_rollingFileAppender" 
                     fileName="./logs/foo-${sys:app.name.suffix}.log"
                     filePattern="./logs/foo-${sys:foo.app.name.suffix}.log.%i">
            <PatternLayout>
                <Pattern>%d|%X{active.profiles}| %-5p |%X{fcp.session}|%X{StateMachine.key}|%X{StateMachine.currentState}| %m | %t | %c{1.}%n</Pattern>
            </PatternLayout>
            <Policies>
                <OnStartupTriggeringPolicy minSize="0" />
                <SizeBasedTriggeringPolicy size="100 MB" />
            </Policies>
            <DefaultRolloverStrategy max="10"/>
        </RollingRandomAccessFile>
    
        <Console  name="_stdOutAppender" target="SYSTEM_OUT">
            <PatternLayout pattern="%d|%X{active.profiles}| %-5p |%X{fcp.session}|%X{StateMachine.key}|%X{StateMachine.currentState}| %m | %t | %c{1.}%n"/>
        </Console>     
      </appenders>
    
        <Loggers>
            <Root level="info">
                <AppenderRef ref="_rollingFileAppender"/>
                <AppenderRef ref="_stdOutAppender" level="WARN" />
            </Root>
        </Loggers>
    </Configuration>
    

    现在,最后(关键)点:通过将系统属性Log4jContextSelector设置为org.apache.logging.log4j.core.async.AsyncLoggerContextSelector来启用log4j 2 async loggers

    这最后一位应该会产生很大的性能差异。 (与禁用控制台日志记录一起使用。)

答案 1 :(得分:0)

我遇到了更奇怪的发现。我启用了“-verbose:class”JVM选项来查看加载了哪些类,并且我可以确认只加载了以下JAR中的类(按顺序):

  • SLF4J-API-1.7.20.jar
  • 的log4j-SLF4J-IMPL-2.6.2.jar
  • 的log4j-API-2.6.2.jar
  • log4j的核 - 2.6.2.jar
  • 的log4j-1.2-API-2.6.2.jar
  • JCL-过SLF4J-1.7.20.jar

然而,以下两项测试会产生不同的结果:

  1. 性能测试包括log4j-over-slf4j-1.7.20&amp; log4j-1.2.16: GOOD
  2. 性能测试包括log4j-over-slf4j-1.7.20&amp;但不包括log4j-1.2.16:BAD
  3. 性能测试,不包括log4j-over-slf4j-1.7.20&amp;包括log4j-1.2.16:BAD
  4. 请注意,这两个JAR根本没有加载。