简体   繁体   English

Quartz SLF4J Log4J 在运行时外部修改到 SocketAppender 的附加程序

[英]Quartz SLF4J Log4J Appenders Modified at Runtime Externally to a SocketAppender

We have an issue with a single customer where Quartz jobs stop running soon after start up.我们遇到了一个客户的问题,即 Quartz 作业在启动后很快就停止运行。 Diagnosing the issue has been very frustrating because Quartz was not properly logging to disk as it usually does for this customer.诊断问题非常令人沮丧,因为 Quartz 没有像通常为该客户所做的那样正确地记录到磁盘。 After several days of hard debugging the production system and using jstack after jobs stop running I was able to observe the main quartz process is IO bound attempting to write to a socket appender... which we have not configured.经过几天对生产系统的硬调试并在作业停止运行后使用 jstack 后,我能够观察到主要的石英进程是 IO 绑定尝试写入套接字附加程序......我们尚未配置。 This is a production QA'd application stack deployed to over 1000 servers yet this issue happens only with one customer on one of their two servers running our software.这是一个部署到 1000 多台服务器的生产 QA 应用程序堆栈,但只有一个客户在他们的两台服务器中的一台上运行我们的软件时才会出现此问题。

After jobs stop executing jstack shows the following for our main quartz thread:在作业停止执行 jstack 后,我们的主要石英线程显示以下内容:

"CIPDCEScheduler_QuartzSchedulerThread" #50 prio=5 os_prio=0 cpu=2609.38ms elapsed=335.10s tid=0x0000026f7c819800 nid=0x1304 runnable  [0x000000fb84ffe000]
   java.lang.Thread.State: RUNNABLE
   at sun.nio.ch.SocketDispatcher.write0(java.base@13.0.1/Native Method)
   at sun.nio.ch.SocketDispatcher.write(java.base@13.0.1/SocketDispatcher.java:54)
   at sun.nio.ch.NioSocketImpl.tryWrite(java.base@13.0.1/NioSocketImpl.java:399)
   at sun.nio.ch.NioSocketImpl.implWrite(java.base@13.0.1/NioSocketImpl.java:414)
   at sun.nio.ch.NioSocketImpl.write(java.base@13.0.1/NioSocketImpl.java:441)
   at sun.nio.ch.NioSocketImpl$2.write(java.base@13.0.1/NioSocketImpl.java:825)
   at java.net.Socket$SocketOutputStream.write(java.base@13.0.1/Socket.java:1007)
   at java.io.ObjectOutputStream$BlockDataOutputStream.drain(java.base@13.0.1/ObjectOutputStream.java:1883)
// IO BOUND !!!                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^
   at java.io.ObjectOutputStream$BlockDataOutputStream.setBlockDataMode(java.base@13.0.1/ObjectOutputStream.java:1792)
   at java.io.ObjectOutputStream.writeSerialData(java.base@13.0.1/ObjectOutputStream.java:1496)
   at java.io.ObjectOutputStream.writeOrdinaryObject(java.base@13.0.1/ObjectOutputStream.java:1433)
   at java.io.ObjectOutputStream.writeObject0(java.base@13.0.1/ObjectOutputStream.java:1179)
   at java.io.ObjectOutputStream.writeObject(java.base@13.0.1/ObjectOutputStream.java:349)
   at <b>org.apache.log4j.net.SocketAppender</b>.append(SocketAppender.java:268)
//       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   at org.apache.log4j.AppenderSkeleton.doAppend(AppenderSkeleton.java:251) 
   - locked <0x00000000c0a0d398> (a org.apache.log4j.net.SocketAppender)
   at org.apache.log4j.helpers.AppenderAttachableImpl.appendLoopOnAppenders(AppenderAttachableImpl.java:66)
   at org.apache.log4j.Category.callAppenders(Category.java:206)
   - locked <0x00000000c0a09ef8> (a org.apache.log4j.spi.RootLogger)
   at org.apache.log4j.Category.forcedLog(Category.java:391)
   at org.apache.log4j.Category.log(Category.java:856)
   at org.slf4j.impl.Log4jLoggerAdapter.debug(Log4jLoggerAdapter.java:205)
   at org.quartz.impl.jdbcjobstore.DBSemaphore.obtainLock(DBSemaphore.java:115)
   at org.quartz.impl.jdbcjobstore.JobStoreSupport.executeInNonManagedTXLock(JobStoreSupport.java:3781)
   at org.quartz.impl.jdbcjobstore.JobStoreSupport.triggerFired(JobStoreSupport.java:2865)
   at org.quartz.core.QuartzSchedulerThread.run(QuartzSchedulerThread.java:319)

The main takeaways from the above stack are highlighted but include "BlockDataOutputStream.drain" (IO Bound) and "org.apache.log4j.net.SocketAppender".上面堆栈的主要内容被突出显示,但包括“BlockDataOutputStream.drain”(IO Bound)和“org.apache.log4j.net.SocketAppender”。 We have only configured a rolling file appender (which is no longer writing).我们只配置了一个滚动文件追加器(不再写入)。 The presence of an IO bound SocketAppender is baffling as we have never configured such an appender and it is IO bound blocking our threads as a result. IO 绑定的 SocketAppender 的存在令人困惑,因为我们从未配置过这样的附加程序,结果它是 IO 绑定阻塞我们的线程。 Our log4j properties are as follows:我们的 log4j 属性如下:

log4j.debug=TRUE
log4j.rootLogger=INFO, R
log4j.appender.R=org.apache.log4j.RollingFileAppender
log4j.appender.R.File=C:/CIP/Server/tmp/scheduler.log
log4j.appender.R.MaxFileSize=5MB
log4j.appender.R.MaxBackupIndex=5
log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss.SSSS} %p %t %c - %m%n

The tomcat logs show that it is processing this log4j configuration on startup: tomcat 日志显示它在启动时正在处理此 log4j 配置:

log4j: Parsing for [root] with value=[INFO, R].
log4j: Level token is [INFO].
log4j: Category root set to INFO
log4j: Parsing appender named "R".
log4j: Parsing layout options for "R".
log4j: Setting property [conversionPattern] to [%d{yyyy-MM-dd HH:mm:ss.SSSS} %p %t %c - %m%n].
log4j: End of parsing for "R".
log4j: Setting property [maxBackupIndex] to [5].
log4j: Setting property [file] to [C:/CIP/Server/tmp/scheduler.log].
log4j: Setting property [maxFileSize] to [5MB].
log4j: setFile called: C:/CIP/Server/tmp/scheduler.log, true
log4j: setFile ended
log4j: Parsed "R" options.
log4j: Finished configuring.

It is my opinion that some how at runtime the logging configuration is being changed by some external source.我认为某些外部源在运行时如何更改日志记录配置。 All of our components are embedded in our application stack, not installed globally, which do not use any global configurations on the server.我们所有的组件都嵌入在我们的应用程序堆栈中,而不是全局安装,不使用服务器上的任何全局配置。 I have checked that no classpath or Java environment variables are defined globally on the server.我检查过服务器上没有全局定义类路径或 Java 环境变量。 The above log4j configuration will create an empty log file on startup but never write to it (but only on this single deployment).上述 log4j 配置将在启动时创建一个空日志文件,但从不写入(但仅在此单个部署中)。

This customer does have SolarWinds installed on this server (and not the other server they have which works fine).该客户确实在此服务器上安装了 SolarWinds(而不是他们拥有的其他运行良好的服务器)。 I can see SolarWinds has its own embedded Java stack including SLF4J / Log4J installed in C:\Windows\SysWOW64/ContegoSPOP.我可以看到 SolarWinds 有自己的嵌入式 Java 堆栈,包括 SLF4J / Log4J 安装在 C:\Windows\SysWOWTEgoConPOP 中。 However, I see no indication that it has any global footprint that should interfere with our software.但是,我没有看到任何迹象表明它有任何影响我们软件的全球足迹。

Does Tomcat and/or SLF4J have some mechanism for discovery or inheritance or modification from a remote process which could change the logging appenders for a Quartz servlent? Tomcat 和/或 SLF4J 是否具有某种发现机制或 inheritance 或远程进程的修改,这可能会更改 Quartz servlent 的日志记录附加程序?

OpenJDK 13 + Tomcat 8.5.73 + Quartz 1.8.6 + SLF4J 1.6.0 + Log4J 1.2.17 OpenJDK 13 + Tomcat 8.5.73 + 石英 1.8.6 + SLF4J 1.6.0 + Log4J 1.2.17

This ended up being a very obscure issue likely to never impact others but I wanted to answer this just in case.这最终成为一个非常模糊的问题,可能永远不会影响其他人,但我想回答这个问题以防万一。 We use PHPJavaBridge for some Java interop with PHP and within that WAR distribution is logic to try and auto-connect to Apache Chainsaw on port 4445. If it connects on that port it some how... magically... reroutes all logging to that port via a socket appender and discards your log4j configurations otherwise. We use PHPJavaBridge for some Java interop with PHP and within that WAR distribution is logic to try and auto-connect to Apache Chainsaw on port 4445. If it connects on that port it some how... magically... reroutes all logging to that端口通过套接字附加程序,否则丢弃您的 log4j 配置。

In our case an unrelated service was bound to port 4445 on the customer server and this odd feature kicked in and routed all of our logs to it.在我们的例子中,一个不相关的服务被绑定到客户服务器上的 4445 端口,这个奇怪的功能启动并将我们所有的日志路由到它。 Since the service on that port was not reading data it would get IO bound and lock the jobs.由于该端口上的服务没有读取数据,它会绑定 IO 并锁定作业。 We were able to disable the obscure feature by setting the following property in Tomcat at runtime:我们可以通过在运行时在 Tomcat 中设置以下属性来禁用模糊功能:

-Dchainsaw.port=0

and I learned a lot along the way...一路上我学到了很多...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM