Java Tomcat自动关机

Java Tomcat自动关机,java,linux,tomcat,Java,Linux,Tomcat,我在CentOS 6.5 64位和OpenJDK 1.7 64上运行Tomcat 7.0.53 我有几个服务器,偶尔——就像每周随机一次一样——Tomcat会优雅地自行关闭。我已经看了几个月了,找不到原因。唯一的模式似乎是长时间没有任何事情发生,然后关闭 我已经升级到最新版本的底层工具(Tomcat、Java等) 我使用默认内存设置运行 我已在server.xml中禁用关机 我已经将MySQL移到了另一个框中,以确保Tomcat是唯一实质性的应用程序(服务器也运行nginx) 我已经验证了我的

我在CentOS 6.5 64位和OpenJDK 1.7 64上运行Tomcat 7.0.53

我有几个服务器,偶尔——就像每周随机一次一样——Tomcat会优雅地自行关闭。我已经看了几个月了,找不到原因。唯一的模式似乎是长时间没有任何事情发生,然后关闭

  • 我已经升级到最新版本的底层工具(Tomcat、Java等)
  • 我使用默认内存设置运行
  • 我已在server.xml中禁用关机
  • 我已经将MySQL移到了另一个框中,以确保Tomcat是唯一实质性的应用程序(服务器也运行nginx)
  • 我已经验证了我的任何代码中都没有System.exit()。我还没有扫描LIB,因为我不知道怎么做。我也不希望在那里找到任何东西。为什么图书馆会退出呢
  • 我已启用垃圾收集日志记录。但它们看起来相当快,就像0.15秒内的完整GC
下面是其中一台服务器的内存使用情况。大量内存可用

                 total       used       free     shared    buffers     cached
    Mem:          2006        771       1234          0        176        281
    -/+ buffers/cache:        313       1692
    Swap:         2047          0       2047
下面是Catalina.out中的一个事件。你可以看到它开始,然后在几个小时内没有任何令人兴奋的事情发生。然后,它优雅地关闭自己,好像有人告诉它

我对这件事研究得很透彻,还没弄明白

有人能为我提出一个行动计划吗

谢谢

从Server.xml文件:

    <Server port="-1" shutdown="__SHUTDOWN__">

有东西在告诉Tomcat关机

Tomcat在“遇到麻烦”(内存不足或其他任何情况)时不会优雅地关闭。当内存不足时,Linux不会优雅地关闭进程,它会使用kill-9强制停止进程,这在Tomcat日志中不会留下任何痕迹

  • kill-15
    将通过关闭钩子优雅地关闭tomcat。(之前的答案是这里的
    kill-3
    ,这只是导致线程转储。)

  • 内部出口()也将通过关闭钩子优雅地关闭它

  • 它可以通过JMX关闭,当然还有来自Catalina的关闭命令

所以,某个地方有人告诉Tomcat这么做。这不是什么未知的内部“问题”。这种事情会直接杀死tomcat,他们不会礼貌地问

您可以尝试的一件事是启用日志的调试,以查看您得到了什么样的聊天。如果获得的信息太多,可以尝试专门查看
org.apache.catalina.core.StandardContext
。这可能不会给你比已经记录的更多的信息,但它可能会告诉你一些事情

在那之后,如果有这样的动机,并且它还在继续,我建议您自己构建Tomcat,并插入一些堆栈跟踪转储

例如,在
org.apache.coyote.AbstractProtcol
中,您可以添加:

Exception e = new Exception("Shut down trace");
getLog().info("Shutting down protocol", e);
转到
stop()
方法

这将给你一个坚实的堆栈跟踪,以了解这是从哪里来的。Tomcat并不是一个真正令人讨厌的事件,它只是一个随机消息的风暴。关闭是相当同步的。因此,堆栈跟踪将为你提供一个可靠的线索,谁开始了聚会。然后你可以从那里看看这是怎么发生的


Tomcat中有很多接口和抽象,但实际上只有少数实现,所以它不是不可穿透的。有一个冒烟的堆栈跟踪将非常有助于将其固定下来。

您的Tomcat是如何启动的?如果存在父进程,则发送到父进程的信号可能是导致完全关闭的原因。

在v7.0.55之前的Tomcat版本中存在一个已知的(已修复的)错误:

这篇文章读起来确实不错,但我可以为你总结一下。启动Tomcat时,会出现一个等待状态,开始等待shutdown命令。这是正常的,但是这些版本中的错误是在大约50天的等待时间内隐式超时。等待状态超时时,Tomcat将关闭

所以在Tomcat中有一些奇怪的事情发生,不,你不是疯子。这发生在我维护了一年多的SOLR集群上,之后我发现了这个bug并通过升级修复了它。没有人注意到,因为崩溃花了太长时间,而且随着时间的推移,找到根本原因变得很容易。最简单的事情就是重新启动Tomcat并忘记它曾经发生过

我希望这个答案对你有帮助。我看到您正在/正在运行带有此错误的版本


祝你好运

DC/OS中的一个案例

最近我们也发生了类似的事件。我们的
tomcat
作为服务在
DC/OS
环境中的docker中运行。stderr只是说tomcat被杀了,在tomcat的任何日志文件中都没有有用的痕迹

原来原因很简单,我们没有为服务分配足够的内存。还有更多的调试建议,但我们使用的关键技术是检查内核日志:

# journalctl -f _TRANSPORT=kernel
...
Mar 29 15:09:09 host-17 kernel: Memory cgroup out of memory: Kill process 7935 (java) score 1021 or sacrifice child
Mar 29 15:09:09 host-17 kernel: Killed process 7906 (java) total-vm:11583840kB, anon-rss:1032860kB, file-rss:30924kB, shmem-rss:0kB
...

一旦我们发现了这一点,我们在DC/OS中增加了服务的内存分配,问题就解决了。

您的Tomcat是如何启动的?如果存在父进程,则发送到父进程的信号可能会导致完全关闭。我建议将
set-m
选项添加到
start\u script.sh

中,使用探查器在live中评估应用程序。您还应该分析堆转储和线程转储,以便更好地了解应用程序中的问题。1) 它正在泄漏线程,请检查您的JDBC驱动程序,这是最常见的源代码。2) 服务器或其应用程序之一已无法恢复地崩溃(例如在本机代码中)。编辑:也显式调用关闭挂钩。:)我最初的直觉是,这不是从服务器内部发生的,操作系统中的某些东西正在导致关机。但我一点也不知道什么是魔法
# journalctl -f _TRANSPORT=kernel
...
Mar 29 15:09:09 host-17 kernel: Memory cgroup out of memory: Kill process 7935 (java) score 1021 or sacrifice child
Mar 29 15:09:09 host-17 kernel: Killed process 7906 (java) total-vm:11583840kB, anon-rss:1032860kB, file-rss:30924kB, shmem-rss:0kB
...