スプリングクロック異常停止の解決策について


背景:機能概要:プロジェクトには、タイミング時計(5分ごと)が製品データをesに増分更新する機能があります.大体論理:単一テーブルで大量のメタデータをredisに追加し、redisのメタデータに基づいて製品データをesに更新します.タイミング時計の構成方法:@Scheduled(cron=「${task.product.incr.cron.」)
現象:時計を何百回も実行すると、異常に停止し、二度と実行せず、毎回サービスを再起動する方法で解決する.
研究したいくつかの点:1.今回の時計は実行が完了しない限り、次の時計は実行しない.
本人はこの問題のいくつかの記録を解決します:前期:方式:各種の最適化プログラム.結果:時計の有効実行回数は増加して、しかしやはり異常に停止します.
中期:同前期
後期:方式:1.大量のログから問題を位置決めして、ある時計の異常停止が間違っていないことを発見して、1つの千次の循環コードを実行する時小さい確率性のプログラムが詰まって死んで、後の時計が実行しないことを招いて、コードの上で原因を位置決めすることができません2.偶然java.util.concurrent.Futureが利用することができることを発見して、Future類の作用:1つの方法にタイムアウト時間を設定することができて、if(タイムアウト)->throw TimeoutException 3.だからコードは:
ExecutorService executorService = Executors.newSingleThreadExecutor();
// callable            
Future<String> future = executorService.submit(callable);
try {
	future.get(20, TimeUnit.MINUTES);
} catch (InterruptedException e) {
	log.info("        (InterruptedException)");
} catch (ExecutionException e) {
	log.info("        (ExecutionException)");
} catch (TimeoutException e) {
	log.info("        (TimeoutException)");
} finally {
	isRuningProductSyncTask = false;
	incrTaskExcuteCount ++;
	log.info("        ,   : {} ", (System.currentTimeMillis() - startTime) / 1000);
}

ここでcallableには、実行する必要があるメソッドが記録されています(20分タイムアウトが設定されています):
Callable<String> callable = new Callable<String>() {
	
	@Override
	public String call() throws Exception {
		try {
			if(incrTaskExcuteCount % fullSyncNum == 0 && incrTaskExcuteCount != 0) {
				log.info("      \"  \"  , incrTaskExcuteCount = {}", incrTaskExcuteCount);
				productFullSync();
			}else {
				log.info("      \"  \"  , incrTaskExcuteCount = {}", incrTaskExcuteCount);
				productIncrSync();
			}
		} catch (Exception e) {
			e.printStackTrace();
			log.error(CLASS_LOG_PREFIX + e.getMessage());
		} 
		return "over";
	}
	
};

4.達成した効果:たとえタイマープログラムが小さい確率で死んでも、20分後に今度のタイマーを飛び出して次のタイマーを実行し続けることができる
結果:理想的には、時計異常停止の問題は発生しなかった
まとめ:根本的にこの問題を解決していない(根本的に解決していない)(/顔を覆う)ので、別の方法でこの問題を解決した.
キーワード:springクロック、クロック停止、クロック異常停止、java,@Scheduled