我有一个简单的 ServletContextListener
,它在 tomcat 启动时运行一个进程,并在 tomcat 关闭时关闭它。
过程:
java -jar application.war -S rake jobs:work
它生成一个处理队列的 ruby delayed_job
worker。但是,当有很多作业要处理或一个作业需要一段时间时,就会出现问题。它处理了一些然后它就停止了。没有错误被抛出,日志中没有任何内容。它只是停止执行。
当我重新启动服务器时,一个条目被放入日志中,表明发送了关闭信号。 Worker 醒来,完成一项工作(如果它在执行期间暂停)并退出。
当我在 tomcat7 之外运行该命令时,它按预期工作正常。
ServletContextListener
代码:
public class RakeServlet implements ServletContextListener
{
private Process workerProcess;
@Override
public void contextInitialized(ServletContextEvent event)
{
workerProcess = Runtime.getRuntime().exec("java -jar application.war -S rake jobs:work");
}
@Override
public void contextDestroyed(ServletContextEvent event)
{
workerProcess.destroy();
}
}
ps aux
输出:
tomcat7 2119 0.5 16.9 3479300 668704 ? Sl 02:20 2:41 java -jar application.war -S rake jobs:wor
最佳答案
问题在于,当运行外部进程时,您必须从子进程中读取stdout
和stderr
流。否则,当输出缓冲区填满时,进程实际上会在 I/O 写入 block 上暂停。
为了正确执行此操作,您需要启动一些线程来监视这些流并清空它们(大概是对输出做一些有用的事情,而不是简单地丢弃它)。
有关更多详细信息,请查看 Steve Liles's blog post on the subject他在其中描述了问题和解决方案的示例。
如果目标进程实际上是另一个 Java 进程,您应该考虑在进程内运行 Java 代码,以避免启动第二个 JVM 的开销以及与之通信的复杂性(即 stdio 流)。
关于java - 由 tomcat7 暂停产生的进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47797038/