2017-08-08 5 views
1

私は、JavaアプリケーションをUbuntu 16.04 LTS上で実行しています。エンドポイントの呼び出し時にシャットダウンスレッドが消える

アプリケーションがシャットダウン信号を受信した場合、シャットダウンシーケンスがこのように実行されます。

Runtime.getRuntime().addShutdownHook(new Thread() { 
     @Override 
     public void run() { 
      shutdown(); 
     } 
    }); 

これは、すぐに私は(私が受信して改修を使用していた外部RESTエンドポイントを呼び出そうとして正常に動作しますが、 Observables)、スレッドはそこで完全に消滅し、エンドポイントは呼び出されず、連続したコマンドはもはや実行されません。

  • 私は最初Observablesが問題になると考えて、Retrofit Callを代わりに使用しました。同じ問題。
  • その後、非同期エンドポイントを呼び出す代わりに、同期呼び出しを試みました。同じ問題。
  • シャットダウンの時間は問題ではありません。私は明示的に30秒を与えた。

これはスレッディングと関連があると想定します。ライブラリがシャットダウン中に余分なスレッドを作成すると、JVMはすべてを殺すようです。

誰かが光を当てたり、私が試してみることができる他のものを提案することができます。

-

追加情報:

私は長時間実行クリーンアップを実行する必要があります。問題は、シャットダウン信号がどのように見えるか、それが起こったときには判断できません。ホストが停止しているときに、docker stopのDockerコンテナで実行され、最初にSIGTERMを送信してから、 、現在60秒)SIGKILL。コンテナ内のJVMは、潜在的に何千ものクライアントに接続できるsocket.ioを実行します。私は各クライアントにgood-byeを送り、これらをきれいに切断し、ロードバランサからサーバを登録解除するのに60秒を使いたいと思う。そのため、クリーンアップ中にブロックする可能性のある操作がたくさんあります。

Javaはクリーンアップが常に不足していると信じている場合は、Javaが間違っている:(

+2

シャットダウンフックはできるだけ早く終了し、確実にネットワーク操作を行わないでください。 Javadocを参照してください。 – EJP

答えて

2

あなたのケースでJVMをシャットダウンすると、中断フラグを発生させます。だから、できるだけ早くあなたが任意のブロック操作を呼び出すように1つはすぐにすることInterruptedExceptionによって終了される可能性があります。

アプリケーションの終了時にさらに長いコードを実行する必要がある場合は、シャットダウンフックは使用できません。新しいもの。

あなたのコードについての詳しい情報はありませんでしたので、私はできません正確な助言を与えるが、一般的な考え方は、アプリケーションが実行されている間にメインスレッドを待機させ、そのアプリケーションをクリーンアップすることである。この場合、システムシャットダウン信号ではないシャットダウン信号が必要なため、アプリケーションは正常に動作し続けます。

それはあまりにも複雑何らかの理由であれば、あなたのような何かをすることによって、あなたのシャットダウンフックの先頭に割り込まフラグをクリアしようとすることができます:

try { 
    Thread.sleep(1); 
} catch (InterruptedException e) { 
} 

これはルール違反があり、そしてそれらが存在します理由のために。 i.E.killシグナルに十分な速さで反応せず、悪い方法で終了させないと、OSはあなたのプログラムがハングアップしていると考えるかもしれません。

+0

これは私の質問に答えます。私はあなたがより多くのアイデアを持っている場合には、上記の追加情報を追加しました。しかし、私はスレッドを中断するのは私ができる唯一のことだと思っています。私の中断されたスレッドが時間通りに終了しないと 'SIGKILL 'を送る" OSはDockerです "というより安全です。 –

関連する問題