0

今天是个好日子。

我无法解决下一个问题:

我们将 WebSphere 应用服务器用于我们的应用程序,并使用“logback”日志框架来管理我们的日志文件。

似乎一切工作正常,但最近我们检测到文件滚动的不可接受行为。对于我们的应用程序在 WebSphere 滚动日志文件(按大小和天数)上的第一次启动效果很好,但是当我们停止应用程序时 - 当前日志文件被 java.exe(IBM WAS)进程锁定并且当我们再次启动应用程序时 -由于先前的锁定,滚动日志不起作用。当我通过 windows Unlocker 查看文件时,我很惊讶 - 有 2 个进程锁定了当前文件。如果我们停止应用程序并重新启动它 - 将有 3 个 java.exe 锁定当前日志文件,尽管在任务管理器中只运行一个进程。有时我会在这种“测试”期间发现 OutOfMemory 错误。

因此,最后我们有非常大的日志文件。(20GB 及以上)

我发现了一些类似的问题,但是 log4j 滚动。并且没有任何解释为什么会这样 - 只是一个就像 - 不建议将 log4j 用于 websphere。

并且似乎根本不完全是“记录器”中的问题。那么,有没有人可以回答2个问题-


  1. 当应用程序已经停止时,为什么 WebSphere 锁定文件而不释放它???

  2. 当应用程序以正确的方式停止时(不使用解锁器、任务管理器等作弊手段),如何释放(或告诉 WebSphere 不要锁定)日志文件的锁定?


感谢您的关注...任何帮助将不胜感激。


更新 1:

最近我尝试使用带有 logback 的小型 Web 应用程序 - 效果很好 - 没有重复锁定。

我还查看了日志,当我们的大应用程序停止时,发现了这个(停止应用程序期间日志中唯一的一个字符串)

27-03 05:59:39 [WebContainer : 7] INFO o.hibernate.impl.SessionFactoryImpl:close - closing

关闭但不关闭?我希望我以正确的方式思考...

----更新 3

嗯...我花了很多时间在 websphere 上部署自定义 WAR,但我仍然无法找出 WAS 有时会锁定日志文件而有时不会锁定的原因。

我不敢相信,我很惊讶没有人面临同样的麻烦

4

1 回答 1

1

这篇文章对我有帮助 - http://logback.qos.ch/manual/jmxConfig.html 虽然我们没有在我们的应用程序中使用任何 JMXConfigurators ...

所以我在 web.xml 中添加了

<listener>
    <listener-class>ru.fns.commonex.listener.CleanUpServletContextListener</listener-class>
</listener>

监听器有下一个代码:

@Override
public void contextDestroyed(ServletContextEvent sce) {
    log.debug("contextDestroyed({}) called.", sce);
    deRegisterLog();
}

/**
* Avoiding memory leaks
*
* If your application is deployed in a web-server or an application server,
* the registration of an JMXConfigurator instance creates a reference from the system class loader
* into your application which will prevent it from being garbage collected when it is stopped or re-deployed,
* resulting in a severe memory leak.
*
* Thus, unless your application is a standalone Java application,
* you MUST unregister the JMXConfigurator instance from the JVM's Mbeans server.
* Invoking the reset() method of the appropriate LoggerContext will automatically unregister any
* JMXConfigurator instance. A good place to reset the logger context is in the contextDestroyed()
* method of a javax.servlet.ServletContextListener.
*/
private void deRegisterLog() {
    LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
    log.info("Trying to stop logger factory {}", lc);
    if (lc != null) {
        lc.stop();
    }
}
于 2013-04-02T10:24:21.617 回答