Tomcat 6上のSpring 3 Webアプリケーションがあり、@Scheduled
を介していくつかのスケジュールされたサービスを使用します(主に毎晩実行されるジョブ用)。たまに(まれに、おそらく2か月に1回程度)スケジューラスレッドが機能しなくなるため、次の夜にはジョブが実行されないようです。ログファイルに例外やログエントリはありません。
なぜこれが起こっているのか誰かに手掛かりがありますか?または、この問題に関する詳細情報を取得するにはどうすればよいですか?
アプリケーション内でこの状況を検出し、スケジューラーを再始動する方法はありますか?
現在、私たちは5分ごとに実行され、ログエントリを作成するロギングジョブを用意することでこれを解決しています。ログファイルの更新が停止した場合(nagiosによって監視)、Tomcatを再起動するときが来たことがわかります。サーバーを完全に再起動せずにジョブを再起動すると便利です。
この質問には非常に多くの票が寄せられたので、私の問題に対する(おそらく非常に具体的な)解決策を投稿します。
Apache HttpClientライブラリを使用して、スケジュールされたジョブでリモートサービスを呼び出します。残念ながら、リクエストの実行時にデフォルトのタイムアウトは設定されていません。設定後
connectTimeout
connectionRequestTimeout
socketTimeout
30秒まで問題はなくなりました。
int timeout = 30 * 1000; // 30 seconds
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(timeout)
.setConnectionRequestTimeout(timeout)
.setSocketTimeout(timeout).build();
HttpClient client = HttpClients.custom()
.setDefaultRequestConfig(requestConfig).build();
これは簡単に見つけることができます。あなたはスタックトレースでこれを行うでしょう。スタックトレースを取得する方法については多くの投稿があり、UNIXシステムでは「kill -3」を実行すると、スタックトレースがcatalina.outログファイルに表示されます。
スタックトレースを取得したら、スケジューラスレッドを見つけて、それが何をしているかを確認します。実行していたタスクがスタックした可能性はありますか?
詳細については、ここにスタックトレースを投稿することもできます。
知っておくべき重要なことは、どのスケジューラを使用するかです。 SimpleAsyncTaskExecutorを使用すると、タスクごとに新しいスレッドが開始され、スケジューリングが失敗することはありません。ただし、完了しないタスクがある場合、最終的にメモリが不足します。
http://docs.spring.io/spring/docs/3.0.x/reference/scheduling.html
私の場合、スタックトレースは完全にクリーンで、スレッドはほんの数回しか開始されませんでした。問題は別のスケジュールと矛盾していた。
更新済み
fixedDelayString
を使用しているため、スケジュールが正しく機能せず、前のジョブが新規開始の時間に終了していませんでした。スケジュールをfixedRateString
に変更した後、スレッドは正しく開始されました。