由 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

问题是,当 运行 外部进程时,您 必须 从子进程读取 stdoutstderr 流。否则,当输出缓冲区填满时,进程实际上会暂停在 I/O 写入块上。

为了正确执行此操作,您需要启动一些线程来监视这些流并清空它们(大概是对输出做一些有用的事情,而不是简单地丢弃它)。

有关详细信息,请查看 Steve Liles's blog post on the subject 他描述了问题和解决方案的示例。

如果目标进程实际上是另一个 Java 进程,您应该考虑 运行 进程内 Java 代码以避免启动第二个 JVM 的开销和与之通信的复杂性(即 stdio 流)。