繁体   English   中英

为什么Log4j2的RollingFile附加程序会阻止独立的应用程序终止60秒?

[英]Why Log4j2's RollingFile appender prevents a stand alone application to terminate for 60 sec?

这段代码重现了我认为是Log4j2的错误。 这是一个简单的循环,它通过两个附加程序记录2000条消息:控制台附加程序和滚动文件附加程序,每5Kb滚动文件一次。 为了重现我认为是错误的缺陷,此限制故意较低。

这是代码。

package bug;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class Example {

    private static final Logger logger = LogManager.getLogger(Example.class);

    public static void main(String[] args) throws InterruptedException {
        for(int i = 0; i<2000; i++){
            logger.info("This is log message #{}.", i);
            Thread.sleep(0);
        }
    }

}

这是log4j2.xml配置文件。

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="TRACE">
    <Appenders>
        <Console name="stdout" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss} %p %m%n"/>
        </Console>
        <RollingFile name="roll-by-size"
                     fileName="target/log4j2/roll-by-size/app.log"
                     filePattern="target/log4j2/roll-by-size/app.%i.log.gz"
                     ignoreExceptions="false"
                     append="false">
            <PatternLayout>
                <Pattern>%d{yyyy-MM-dd HH:mm:ss} %p %m%n</Pattern>
            </PatternLayout>
            <Policies>
                <OnStartupTriggeringPolicy/>
                <SizeBasedTriggeringPolicy
                        size="5 KB"/>
            </Policies>
        </RollingFile>
    </Appenders>
    <Loggers>
        <Logger name="bug" level="TRACE">
            <AppenderRef ref="roll-by-size"/>
        </Logger>
        <Root level="DEBUG">
            <AppenderRef ref="stdout"/>
        </Root>
    </Loggers>
</Configuration>

奇怪的是,当启动应用程序时,您将在控制台中看到此日志。

2016-12-22 22:12:36 INFO This is log message #1993.
2016-12-22 22:12:36 INFO This is log message #1994.
2016-12-22 22:12:36 INFO This is log message #1995.
2016-12-22 22:12:36 INFO This is log message #1996.
2016-12-22 22:12:36 INFO This is log message #1997.
2016-12-22 22:12:36 INFO This is log message #1998.
2016-12-22 22:12:36 INFO This is log message #1999.
2016-12-22 22:13:36,380 pool-1-thread-1 DEBUG Stopping LoggerContext[name=60199c81, org.apache.logging.log4j.core.LoggerContext@4597ec68]
2016-12-22 22:13:36,380 pool-1-thread-1 DEBUG Stopping LoggerContext[name=60199c81, org.apache.logging.log4j.core.LoggerContext@4597ec68]...
2016-12-22 22:13:36,381 pool-1-thread-1 TRACE Unregistering 1 MBeans: [org.apache.logging.log4j2:type=60199c81]
2016-12-22 22:13:36,381 pool-1-thread-1 TRACE Unregistering 1 MBeans: [org.apache.logging.log4j2:type=60199c81,component=StatusLogger]
2016-12-22 22:13:36,381 pool-1-thread-1 TRACE Unregistering 1 MBeans: [org.apache.logging.log4j2:type=60199c81,component=ContextSelector]
2016-12-22 22:13:36,381 pool-1-thread-1 TRACE Unregistering 2 MBeans: [org.apache.logging.log4j2:type=60199c81,component=Loggers,name=bug, org.apache.logging.log4j2:type=60199c81,component=Lo
ggers,name=]
2016-12-22 22:13:36,381 pool-1-thread-1 TRACE Unregistering 2 MBeans: [org.apache.logging.log4j2:type=60199c81,component=Appenders,name=roll-by-size, org.apache.logging.log4j2:type=60199c81,c
omponent=Appenders,name=stdout]
2016-12-22 22:13:36,382 pool-1-thread-1 TRACE Unregistering but no MBeans found matching 'org.apache.logging.log4j2:type=60199c81,component=AsyncAppenders,name=*'
2016-12-22 22:13:36,382 pool-1-thread-1 TRACE Unregistering but no MBeans found matching 'org.apache.logging.log4j2:type=60199c81,component=AsyncLoggerRingBuffer'
2016-12-22 22:13:36,382 pool-1-thread-1 TRACE Unregistering but no MBeans found matching 'org.apache.logging.log4j2:type=60199c81,component=Loggers,name=*,subtype=RingBuffer'
2016-12-22 22:13:36,382 pool-1-thread-1 TRACE Stopping XmlConfiguration[location=C:\Users\danidemi\workspace\bug-log4j2-hanging-up-before-shutdown\target\classes\log4j2.xml]...
2016-12-22 22:13:36,382 pool-1-thread-1 TRACE XmlConfiguration notified 3 ReliabilityStrategies that config will be stopped.
2016-12-22 22:13:36,382 pool-1-thread-1 TRACE XmlConfiguration stopping 2 LoggerConfigs.
2016-12-22 22:13:36,382 pool-1-thread-1 TRACE XmlConfiguration stopping root LoggerConfig.
2016-12-22 22:13:36,382 pool-1-thread-1 TRACE XmlConfiguration notifying ReliabilityStrategies that appenders will be stopped.
2016-12-22 22:13:36,382 pool-1-thread-1 TRACE XmlConfiguration stopping remaining Appenders.
2016-12-22 22:13:36,383 pool-1-thread-1 DEBUG Shutting down RollingFileManager target/log4j2/roll-by-size/app.log
2016-12-22 22:13:36,383 pool-1-thread-1 DEBUG Shut down RollingFileManager target/log4j2/roll-by-size/app.log, all resources released: true
2016-12-22 22:13:36,383 pool-1-thread-1 DEBUG Shutting down OutputStreamManager SYSTEM_OUT.false.false
2016-12-22 22:13:36,383 pool-1-thread-1 DEBUG Shut down OutputStreamManager SYSTEM_OUT.false.false, all resources released: true
2016-12-22 22:13:36,384 pool-1-thread-1 TRACE XmlConfiguration stopped 2 remaining Appenders.
2016-12-22 22:13:36,384 pool-1-thread-1 TRACE XmlConfiguration cleaning Appenders from 3 LoggerConfigs.
2016-12-22 22:13:36,384 pool-1-thread-1 DEBUG Stopped XmlConfiguration[location=C:\Users\danidemi\workspace\bug-log4j2-hanging-up-before-shutdown\target\classes\log4j2.xml] OK
2016-12-22 22:13:36,385 pool-1-thread-1 DEBUG Stopped LoggerContext[name=60199c81, org.apache.logging.log4j.core.LoggerContext@4597ec68]...

奇怪的是最后一个日志是在某个时间发布的...

2016-12-22 22:12:36 INFO This is log message #1999.

但是log4j2的关闭恰好在最后一条“业务”日志消息之后一分钟开始。

2016-12-22 22:13:36,380 pool-1-thread-1 DEBUG Stopping LoggerContext[name=60199c81, org.apache.logging.log4j.core.LoggerContext@4597ec68]

这就是问题! 业务逻辑终止,但是log4j2等待一分钟,然后允许该应用停止! 为什么 ? 我希望该应用程序可以像人们期望的那样立即停止。

我调查了一下... 60秒的延迟似乎或多或少与记录的消息数量无关。

但是,如果您更改log4j2.xml将大小从log4j2.xml ...

<Policies>
    <OnStartupTriggeringPolicy/>
    <SizeBasedTriggeringPolicy size="5 KB"/>
</Policies>

至5Mb ...

<Policies>
    <OnStartupTriggeringPolicy/>
    <SizeBasedTriggeringPolicy size="5 MB"/>
</Policies>

...,使应用程序在最后一条日志消息之后立即停止。 5Mb是一个足够大的限制,不需要实际进行滚动。 因此,我认为正是滚动本身以某种方式导致了这种延迟的发生。 我认为这是一个错误,但是...您认为呢?

我在GitHub上建立了一个小型Maven项目,演示了我在这里试图解释的内容。

感谢您向Log4j2社区提出此问题

根本原因是Log4j创建了两个ThreadPoolExecutor,一个守护程序和一个非守护程序。 这些执行程序是使用默认设置创建的,该默认设置将线程keepAliveTime设置为一分钟。

在该示例中,应用程序在触发过渡后立即关闭。 翻转将非守护程序执行程序中的旧文件压缩到后台线程中。 因为执行程序使该线程保持活动状态一分钟,而这是一个非守护程序线程,所以整个应用程序将保持活动状态一分钟。

这只会影响过渡后立即退出的应用程序。

更新2016-12-26:此问题已修复。 从2.8开始,默认情况下,非守护程序线程将具有较短(一秒)的keepAliveTime。

您可以尝试使用LogManager.shutdown()作为程序的最后一个命令。

暂无
暂无

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

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