我正在尝试将我的应用程序迁移到使用log4j2 . 它目前使用的是log4j 1.2.16 . 我的项目也有性能构建,升级到log4j 2后,性能似乎有了很大提高 .
也就是说,直到我读到关于桥接的信息 . 根据文档,我必须从类路径中排除log4j1 JAR,并包括桥接JAR - 我假设它被命名为'org.apache.logging.log4j:log4j-1.2-api' . 一旦我这样做,性能再次下降 .
总结一下:
-
性能与log4j2桥接jar log4j-1.2-api log4j1:好
-
使用log4j2桥接jar log4j-1.2-api的性能:糟糕(以至于它回退到只有log4j1的性能)
我已经检查过log4j-1.2-api是否在类路径中较早 . 所以应该先加载它 .
知道什么可能导致这个问题吗?
非常感谢你提前!
哦,我完整的日志记录类路径是:
-
org.slf4j:slf4j-api
-
org.slf4j:log4j-over-slf4j
-
org.slf4j:jcl-over-slf4j
-
org.apache.logging.log4j:log4j-slf4j-impl
-
org.apache.logging.log4j:log4j-core
-
org.apache.logging.log4j:log4j-api
-
org.apache.logging.log4j:log4j-1.2-api
-
log4j:log4j(有和没有,如上所述)
版本:
-
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>
EDIT: 这是包含在类路径中的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>
EDIT 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
Classpath顺序以获得良好的性能
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 回答
我遇到了更奇怪的发现 . 我启用了“-verbose:class”JVM选项来查看加载了哪些类,我可以确认只加载了以下JAR中的类(按顺序):
slf4j-api-1.7.20.jar
log4j-slf4j-impl-2.6.2.jar
log4j-api-2.6.2.jar
log4j-core-2.6.2.jar
log4j-1.2-api-2.6.2.jar
jcl-over-slf4j-1.7.20.jar
然而,以下两个测试产生不同的结果:
性能测试包括log4j-over-slf4j-1.7.20和log4j-1.2.16:GOOD
性能测试包括log4j-over-slf4j-1.7.20&但不包括log4j-1.2.16:BAD
性能测试,不包括log4j-over-slf4j-1.7.20,包括log4j-1.2.16:BAD
请注意,这两个JAR根本没有加载 .
我在这里有两个问题:
为什么在某些类路径配置中使用log4j 1
为什么log4j 2不比log4j 1快
1. Why is log4j 1 used
我怀疑以下slf4j依赖项导致使用旧的log4j 1.2:
如果您使用maven,即使您没有在POM中明确声明,也可以将旧Log4j 1作为传递依赖项引入 .
请删除这些 . Log4j 2具有log4j-slf4j-impl和log4j-jcl模块,它们将完成相同的操作,但使用Log4j 2代替 .
你不应该在类路径中有Log4j 1 . 如果您的应用程序(或您使用的任何库)依赖于Log4j 1 API,则添加log4j-1.2-api模块 .
2. Why is log4j 2 not faster than log4j 1
您描述的配置不利用log4j 2功能 . 它使用AsyncAppender(在log4j 1和2中大致相当)和ConsoleAppender(在log4j 2中略差) . ConsoleAppender is about 60 times slower比文件appender . 在 生产环境 系统中登录控制台时要格外小心 .
以下是我的建议: remove 以下(现在似乎表现更好,但请耐心等待)
log4j-over-slf4j-1.7.20
log4j-1.2.16
旧的lo4j.xml配置
Add LMAX Disruptor依赖:
使用以下log4j2.xml配置 . 暂时只是把它变成一个没有包含的简单文件,你可以稍后再把它放回去 . (注意我将
<Configuration status="trace"
添加到文件的开头:这将输出内部log4j2调试语句,这样您就可以确认配置完成没有问题 . )请注意,由于我怀疑它会影响性能,因此我将控制台记录WARN级别 .
现在,最后(关键)点: enable log4j 2 async loggers 通过将系统属性
Log4jContextSelector
设置为org.apache.logging.log4j.core.async.AsyncLoggerContextSelector
.最后一点应该会产生很大的性能差异 . (与禁用控制台日志记录一起使用 . )