2017-12-13 7 views
0

私は単純なServletContextListenerを持っています。これは、tomcatが起動するときにプロセスを実行し、tomcatがシャットダウンしたときにシャットダウンします。tomcat7によって生成されたプロセスは一時停止する

プロセス:

java -jar application.war -S rake jobs:work 

それはキューを処理ルビー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

tomcatからではなくコマンドラインから実行すると、処理が停止したときにコンソールに何が表示されますか? – Sam

+0

@Samコマンドラインから実行すると処理が停止しない – Ruslan

+0

申し訳ありませんが、もっと慎重に読むべきです。アプリケーションを使用する際に使用する出力ストリームを読み書きする必要がある可能性があります。そうしないと、アプリケーションがハングアップする可能性があります。あなたはwarファイルを直接ロードしてランタイムコールを避けるためにtomcatを使用できますか? – Sam

答えて

0

問題は外部プロセスの実行時に子プロセスからstdoutstderrストリームの両方を読まなければならないということです。それ以外の場合、出力バッファがいっぱいになると、プロセスは事実上I/O書き込みブロックで一時停止します。

これを正しく実行するには、ストリームを監視して空にするためにいくつかのスレッドを開始する必要があります(おそらく、出力に役立つものを単に廃棄するのではない)。

詳細については、Steve Liles's blog post on the subjectを参照してください。ここでは、問題とその解決策の例について説明しています。

ターゲットプロセスが実際に別のJavaプロセスである場合は、Javaコードをインプロセスで実行して、2番目のJVMを起動するオーバーヘッドとその通信の複雑さ(stdioストリーム)を回避することを検討する必要があります。

+0

そのプロセスを一括してデタッチすることはできますか? – Ruslan

+0

@Ruslanあなたは、シェルからのプロセスを "バックグラウンド"するのと同じ意味ですか?いいえ、私はJavaの中からそうする方法はないと思います。ストリームバッファは常に問題になります。私は、Java内から、これらのストリームを例えばストリームに再マッピングする方法がないことを知っています。既に開いているネイティブのファイル記述子。 –

関連する問題