我有简单的ServletContextListener
,它在tomcat启动时运行一个进程,在tomcat关闭时关闭它。
过程:
java -jar application.war -S rake jobs:work
它产生了一个处理队列的ruby delayed_job
工作者。但是,当需要处理大量工作或工作需要一段时间时,就会出现问题。它会处理一些然后它就会停止。没有错误被抛出,日志中没有任何内容。它只是暂停执行。
当我重新启动服务器时,会在日志中输入一个已发送关闭信号的条目。工作人员醒来,完成一项工作(如果在执行期间暂停)并退出。
当我在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
答案 0 :(得分:0)
问题是,在运行外部进程时,必须从子进程中读取stdout
和stderr
个流。否则,当输出缓冲区填满时,该进程会在I / O写入块上有效地暂停。
为了正确地执行此操作,您需要启动一些线程来监视这些流并清空它们(可能是对输出执行一些有用的操作而不是简单地丢弃它)。
有关详细信息,请查看Steve Liles's blog post on the subject,其中描述了问题以及解决方案的示例。
如果目标进程实际上是另一个Java进程,则应该考虑在进程中运行Java代码,以避免启动第二个JVM的开销以及与之通信的复杂性(即stdio流)。