由 tomcat7 暂停产生的进程
Process spawned by tomcat7 pauses
我有一个简单的 ServletContextListener
,当 tomcat 启动时 运行 是一个进程,当 tomcat 关闭时它会关闭。
进程:
java -jar application.war -S rake jobs:work
它生成一个 ruby delayed_job
处理队列的工作程序。但是,当有很多作业要处理或一个作业需要一段时间时,就会出现问题。它处理了一些然后它就停止了。没有错误被抛出,日志中没有任何内容。它只是停止执行。
当我重新启动服务器时,日志中有一个条目表明已发送关闭信号。 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 写入块上。
为了正确执行此操作,您需要启动一些线程来监视这些流并清空它们(大概是对输出做一些有用的事情,而不是简单地丢弃它)。
有关详细信息,请查看 Steve Liles's blog post on the subject 他描述了问题和解决方案的示例。
如果目标进程实际上是另一个 Java 进程,您应该考虑 运行 进程内 Java 代码以避免启动第二个 JVM 的开销和与之通信的复杂性(即 stdio 流)。
我有一个简单的 ServletContextListener
,当 tomcat 启动时 运行 是一个进程,当 tomcat 关闭时它会关闭。
进程:
java -jar application.war -S rake jobs:work
它生成一个 ruby delayed_job
处理队列的工作程序。但是,当有很多作业要处理或一个作业需要一段时间时,就会出现问题。它处理了一些然后它就停止了。没有错误被抛出,日志中没有任何内容。它只是停止执行。
当我重新启动服务器时,日志中有一个条目表明已发送关闭信号。 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 写入块上。
为了正确执行此操作,您需要启动一些线程来监视这些流并清空它们(大概是对输出做一些有用的事情,而不是简单地丢弃它)。
有关详细信息,请查看 Steve Liles's blog post on the subject 他描述了问题和解决方案的示例。
如果目标进程实际上是另一个 Java 进程,您应该考虑 运行 进程内 Java 代码以避免启动第二个 JVM 的开销和与之通信的复杂性(即 stdio 流)。