问题描述
我正在使用log4j用于在聚类环境中运行的Web应用程序.在少数情况下,对于某些过程(不是特定的),丢失了记录.我无法确定原因.在单个服务器实例上运行时,它可以正常工作.我正在使用每日滚动文件附录.是否需要添加/修改其他属性?异步Appender会有所帮助吗?对此有任何解决方案吗?
编辑:以下是我打算使用
的andncappender的log4j xml<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"> <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="true"> <appender name="appLog" class="org.apache.log4j.DailyRollingFileAppender"> <param name="File" value="/logs/app.log" /> <param name="DatePattern" value="'.'yyyy-MM-dd" /> <param name="Threshold" value="DEBUG" /> <param name="Append" value="true" /> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%d [%t] %-5p (%F:%L) - %m%n" /> </layout> </appender> <appender name="async" class="org.apache.log4j.AsyncAppender"> <param name="BufferSize" value="256" /> <param name="LocationInfo" value="true"/> <appender-ref ref="appLog" /> </appender> <root> <priority value="debug" /> <appender-ref ref="async" /> </root> </log4j:configuration>
推荐答案
没有附加log4j配置,再加上有关群集拓扑的一些信息,就不可能确保知道,但是:如果如何配置log4j之间存在不匹配,那么您所描述的可能会发生什么情况. ,以及如何配置为在集群中运行的应用程序.
例如,如果两个群集成员都在同一物理计算机上运行,并且您的应用程序在两个实例中使用了相同的log4j配置文件,则有效地,您有两个不同的JVM登录一次相同的文件.这不会很好地工作.
一般来说,您应该避免两个不同的类负载器写入相同物理文件的情况.
update (log4j.xml的附件之后):假设您的群集服务器在同一物理机器上运行,您附加的配置最终会以多个log4j配置记录到相同的物理文件中( log4j" Live"在classloader的上下文中,并且您有多个服务器 - 因此,在同一台物理机器上).这是行不通的,因为两个log4j"实例"没有办法将写作同步到该文件中.
AsyncAppender不会为您提供帮助. AsyncAppender所做的就是它缓冲日志记录请求,因此您的程序在之前获得了控制实际写了日志线.它不能解决将写作同步到同一文件的问题.
有两种解决方法:
- 将每个JVM登录到其他日志文件中.实际上,让它开枪并见证它有效.
- 而是使用SocketAppender.您所有的日志记录(从所有服务器实例中)最终将通过网络连接发送,并且服务器程序(Log4J提供)将收集它们并将其写入文件中.说明如何使用它可以找到在这里.
其他推荐答案
根据 Isaac 的建议
有两种解决方法:
将每个JVM登录到其他日志文件中.实际上,让它开枪并见证它有效
改用套接字申请人.您所有的日志记录(来自所有服务器实例)最终将通过网络连接发送,并且 服务器程序(由log4j提供)将收集它们并编写它们 进入文件.说明如何使用它可以在此处找到.
对于点1,下面的方法可以工作:
使用:
<param name="File" value="${sys:log4j.logFile}" />
而不是:
<param name="File" value="/logs/app.log" />
JVM1设置JVM属性: log4j.logfile =/logs/ jvm1 /app.log
JVM2设置JVM属性: log4j.logfile =/logs/ jvm2 /app.log
问题描述
I am using log4j for a web application running in clustered environment. Under few circumstances the logging is lost for some of the processes (not particular). I am not able to pin point why. When run on single server instance, it works fine. I am using a daily rolling file appender. Any additional attributes to be added/modified ? Will Async Appender help ? Any solution on this ?
EDIT : Following is log4j XML along with AsyncAppender that I am planning to use
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"> <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="true"> <appender name="appLog" class="org.apache.log4j.DailyRollingFileAppender"> <param name="File" value="/logs/app.log" /> <param name="DatePattern" value="'.'yyyy-MM-dd" /> <param name="Threshold" value="DEBUG" /> <param name="Append" value="true" /> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%d [%t] %-5p (%F:%L) - %m%n" /> </layout> </appender> <appender name="async" class="org.apache.log4j.AsyncAppender"> <param name="BufferSize" value="256" /> <param name="LocationInfo" value="true"/> <appender-ref ref="appLog" /> </appender> <root> <priority value="debug" /> <appender-ref ref="async" /> </root> </log4j:configuration>
推荐答案
Without you attaching your Log4J configuration, plus some information about your cluster topology, it is impossible to know for sure, but: what you're describing that could very well happen if there's a mismatch between how you configure Log4J, and how your application is configured to run in a cluster.
For example, if both cluster members run on the same physical machine, and your application is using the very same Log4J configuration file in both instances, then effectively, you have two different JVM's logging into the same files at once. That isn't going to work very well.
Generally speaking, you should avoid a situation in which two different classloaders write into the same physical files.
UPDATE (following attachment of log4j.xml): assuming that your clustered servers run on the same physical machine, the configuration you attached will end up with multiple log4j configurations logging into the same physical files (log4j "lives" in the context of a classloader, and you have multiple servers - hence multiple classloaders, on the same physical machine). This is not going to work, because the two log4j "instances" don't have a way to synchronize writing into that file.
An AsyncAppender isn't going to help you. All that AsyncAppender does is that it buffers the logging requests so your program gets control before the log lines are actually written. It doesn't solve the problem of synchronizing writing into the very same file.
There are two ways to resolve it:
- Have each JVM log into a different log file. Actually, give it a shot and witness that it works.
- Use a SocketAppender instead. All your logging (from all server instances) will end up being sent over a network connection, and a server program (provided by log4j) will collect them and write them into a file. Explanation how to use it can be found here.
其他推荐答案
As per suggestion given by Isaac to avoid a situation in which two different classloaders/jvm write into the same physical log file:
There are two ways to resolve it:
Have each JVM log into a different log file. Actually, give it a shot and witness that it works
Use a SocketAppender instead. All your logging (from all server instances) will end up being sent over a network connection, and a server program (provided by log4j) will collect them and write them into a file. Explanation how to use it can be found here.
For point#1, below approach can work:
Use:
<param name="File" value="${sys:log4j.logFile}" />
Instead:
<param name="File" value="/logs/app.log" />
For JVM1 set the JVM property: log4j.logFile=/logs/jvm1/app.log
For JVM2 set the JVM property: log4j.logFile=/logs/jvm2/app.log