log4j2的性能与log4j1相比

我正在尝试将我的应用程序迁移到使用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的性能)

我已经检查过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(有和没有,如上所述)

版本:

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

我的配置文件如下:

          

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

     %d|%X{active.profiles}| %-5p |%X{fcp.session}|%X{StateMachine.key}|%X{StateMachine.currentState}| %m | %t | %c{1.}%n                  

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

                                                           

编辑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 

我遇到了更奇怪的发现。 我启用了“-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和log4j-1.2.16:GOOD
  2. 性能测试包括log4j-over-slf4j-1.7.20&但不包括log4j-1.2.16:BAD
  3. 排除log4j-over-slf4j-1.7.20并包括log4j-1.2.16的性能测试:BAD

请注意,这两个JAR根本没有加载。

我在这里有两个问题:

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

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 2function。 它使用AsyncAppender(在log4j 1和2中大致相当)和ConsoleAppender(在log4j 2中略差)。 ConsoleAppender比文件appender 慢大约60倍 。 在生产系统中登录控制台时要格外小心。

这是我的建议: 删除以下(现在似乎提供更好的性能,但忍受我)

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

添加 LMAX Disruptor依赖项:

   com.lmax disruptor 3.2.0  

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

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

      %d|%X{active.profiles}| %-5p |%X{fcp.session}|%X{StateMachine.key}|%X{StateMachine.currentState}| %m | %t | %c{1.}%n                   

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

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