8

以下の@Scheduledように、1 時間ごとに cron 式を使用してSpring をセットアップしました。trend.olap.local.loading.cron.expression0 0 * * * ?

@Scheduled(cron = "${trend.olap.local.loading.cron.expression}")
public void loadHoulyDataToLocalOlap() {
    try {
        // To calculate prev hour;
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.HOUR, -1);
        Date date = cal.getTime();
        int hour = cal.get(Calendar.HOUR_OF_DAY);
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("Loading hourly data into local olap :" + date
                    + ", and hour :" + hour);
        }

        dataIntegrationProcessor.loadHourlyDataToLocalOlap(hour);

        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("Loading hourly data into local olap :" + date
                    + ", and hour :" + hour + " Completed.");
        }
    } catch (Exception e) {
        LOGGER.error("Error occured at loadHoulyDataToLocalOlap", e);
    }
}

ここでの目的は、現在の日付と時刻から時間の値を取得し、それをエグゼキューター メソッドに渡すことです。

基本的に、17:00 に時間の値が 16 になるように、現在の時間から 1 を引いています。

しかし、ログを見ると、時間の値は 15 です。これは、スケジューラが 16:59:59,831 頃に実行されたためです。以下の log4j ログを参照してください。cron ジョブがミリ秒単位で四捨五入され、17:00:00,000 の数ミリ秒前にトリガーされているようです。

このため、間違った値を取得しており、ビジネス ケースが失敗しています。

数ミリ秒前ではなく、1 時間ごとに正確に 0 番目のミリ秒で cron を実行するにはどうすればよいですか?

DEBUG 2013-09-29 16:59:59,831 (TrendScheduler.java loadHoulyDataToLocalOlap:57) - Loading hourly data into local olap :Sun Sep 29 15:59:59 IST 2013, and hour :15
DEBUG 2013-09-29 16:59:59,831 (DataIntegrationProcessor.java loadHourlyDataToLocalOlap:57) - Loading hourly data for hour :15
INFO 2013-09-29 17:00:00,054 (KettleJobExecutor.java executeJob:73) - Job (24hr_populate_hour_data_job.kjb) executed successfully
DEBUG 2013-09-29 17:00:00,054 (TrendScheduler.java loadHoulyDataToLocalOlap:64) - Loading hourly data into local olap :Sun Sep 29 15:59:59 IST 2013, and hour :15 Completed.
4

3 に答える 3

4

短い答えは、オプションではできないということですcron。cron 式の解像度は秒単位であるため、最も近い秒に丸められます。少なくとも特定の時間の後に発生することを保証できる場合がありますが、cron で正確に発生するわけではありません。

あなたの最善の策は、独自の を実装することTriggerです。インターフェイスには、次の実行 (ミリ秒単位)Triggerを返す単一のメソッドがあります。java.util.Dateそこから、次のドキュメントに示されているように、タスクとトリガーを登録できます

于 2014-08-19T16:39:40.270 に答える
1

正しい時間の値を挿入することを意図している場合、より良い解決策は、予測しにくいcronスケジュールに基づいて時間を計算することだと思います。1 秒以内であれば、単純に currenttime を取得して最も近い時間に変換し、そこから時間の値を導き出すことができます。また、警告/アラートを追加して、1 分以上遅れて開始されたタスクや 10 分遅れて開始されたタスクなどをリッスンすることで、cron が不安定な動作をしているかどうかを知らせることもできます。

代わりにcronスケジュールを調整することもできますが、その時点で概算を概算しているため、コードで処理するよりもハックだと思います。単純な 100 ミリ秒以上のオフセットを処理するために、コードをより詳細に制御できます。

于 2014-08-23T00:19:37.030 に答える
0

Cron はミリ秒単位を無視し、システムに突然の負荷がかかるなどのタイミングの問題が他にないと仮定すると、暗黙のうちに 1 秒以内の精度になります。

2 つの選択肢があります。 1. 時間の数秒後に cron ジョブを開始します。 2. 時間の計算を変更して、ジョブが早期にトリガーされるようにします。

2 つのうち、最初の方法が最も簡単で、浮動小数点数を使用する際に丸めの問題を許容する以上にハッカー的とは言えません。

于 2014-08-21T20:49:30.437 に答える