数秒ごとにhangfireの定期的なジョブを設定する方法はありますか?ファイアアンドフォーゲットタスクが別のファイアアンドフォーゲットタスクを作成する解決策を探していません。そうでない場合、推奨される代替策は何ですか?
これがいつサポートされるようになったのかはわかりませんが、Hangfire 1.7.0を備えたASP.NET Core 2.0でこれを試しました。次のコードは、20秒ごとにジョブをスケジュールします。
RecurringJob.AddOrUpdate<SomeJob>(
x => x.DoWork(),
"*/20 * * * * *");
Hangfireが NCrontab を使用して6つのトークンでのcron式を許可しているため(標準の5トークンではなく)、6トークンが誤っていない場合はサポートされます(分単位ではなく2分単位)。
Hangfireダッシュボードも、実行間の短い時間間隔を適切に表示します。
1分未満の繰り返しトリガーを許可しないことに反対する人は、近視眼だと思います。結局のところ、55秒は1分よりも効率が悪いのですか?それはとても恣意的です!私はHangfireが大好きですが、55秒ごとにジョブを実行するというビジネス要件があるため、クライアントをQuartz.netに誘導しなければならない状況に遭遇しました。
1秒ごとに実行するように構成されている場合、パフォーマンスに重大な影響を与えると反論する人は誰もが再び物事を閉じた見方をしています。もちろん、1秒間隔のトリガーはお勧めできませんが、誰かが1秒を選択するというまれな状況で55秒または45秒を破棄しますか?
いずれの場合でも、パフォーマンスは主観的であり、ホストのプラットフォームとハードウェアに依存します。パフォーマンスに関しては、意見を強制するのは実際にはAPIの責任ではありません。ポーリング間隔を設定し、繰り返しをトリガーするだけです。これにより、ユーザーは自分にとって最良の結果を決定できます。
55秒ごとに実行するようにジョブを調整するバックグラウンドプロセスを選択することもできますが、それだけでは十分ではありません。この場合、プロセスはHangfire UIを介して表示されないため、管理者には表示されません。このアプローチはHangfireの主要な利点の1つを回避していると思います。
もしHangfireがQuartz.netのようなものと真剣な競争相手であったならば、それは少なくともそれらの基本的な機能と一致するでしょう。 Quartzが1分未満の間隔でトリガーをサポートできる場合、なぜハングファイアできないのですか?
Hangfireでは1分未満のタスクをスケジュールすることはできませんが、実際には、関数自体を再帰的にスケジュールすることでこれを実現できます。つまり、起動時にメソッドを呼び出すバックグラウンドジョブをスケジュールできる2秒ごとにヒットするメソッドがあるとします。
BackgroundJob.Schedule(() => PublishMessage(), TimeSpan.FromMilliseconds(2000));
次に、PublishMessageメソッドで作業を行い、同じメソッドを呼び出すジョブをスケジュールします。
public void PublishMessage()
{
/* do your stuff */
//then schedule a job to exec the same method
BackgroundJob.Schedule(() => PublishMessage(), TimeSpan.FromMilliseconds(2000));
}
オーバーライドする必要があるもう1つのことは、デフォルトの15秒のSchedulePollingIntervalです。それ以外の場合、メソッドは15秒ごとにのみヒットします。そのためには、スタートアップのBackgroundHobServerOptionsのインスタンスをUseHangfireServerに渡すだけです。
var options = new BackgroundJobServerOptions
{
SchedulePollingInterval = TimeSpan.FromMilliseconds(2000)
};
app.UseHangfireServer(options);
私のソリューションがどのように「フールプルーフ」であるかはわかりませんが、私はそれで自分の目標を達成することができ、すべてが本番環境で「満足」しています。
Hangfireは、定期的なジョブの1分未満の間隔をサポートしていません。
どうして?彼らが1分未満を許可したと想像してください:1秒としましょう。 hangfireはどのくらいの頻度でデータベース内の定期的なジョブをチェックしますか?これにより、データベースIOが大量に発生します。
詳細については、Hangfireの このディスカッション を参照してください。
私は同じことをしなければなりませんでしたが、5秒でした。デフォルトのスケジュールポーリング間隔は15秒に設定されています。したがって、5秒間隔のジョブを実行するには2つのステップが必要です。
startup.cs
var options = new BackgroundJobServerOptions
{
SchedulePollingInterval = TimeSpan.FromMilliseconds(5000)
};
app.UseHangfireDashboard();
app.UseHangfireServer(options);
あなたの仕事
RecurringJob.AddOrUpdate(() => YourJob(), "*/5 * * * * *");
私は同じ問題に直面しました、そしてここにそれが私の解決策です:
private void TimingExecuteWrapper(Action action, int sleepSeconds, int intervalSeconds)
{
DateTime beginTime = DateTime.UtcNow, endTime;
var interval = TimeSpan.FromSeconds(intervalSeconds);
while (true)
{
action();
Thread.Sleep(TimeSpan.FromSeconds(sleepSeconds));
endTime = DateTime.UtcNow;
if (endTime - beginTime >= interval)
break;
}
}
intervalSecondsは最小のNCRON間隔です。 1分です。アクションは私たちの仕事のコードです。また、同時実行性の衝突を回避するために、DisableConcurrentExecutionを使用することをお勧めします。
15秒ごとに実行する必要のある定期的なジョブがあるという点で、同様の要件がありました。この制限を回避するために私が試みたのは、スケジュールされたジョブ(1分間隔に設定)の作成を遅らせることでした。しかし、私が見つけたのは、ポーリング間隔(schedulepolling間隔を自分の頻度に設定)と新しいジョブの取得の遅延を考慮すると、これは必ずしも正確であるとは限らないが、現時点ではトリックを実行しているということです。 。しかし、より良い/適切なソリューションが良いでしょう。
以下のアプローチに解決しなければならないことは少し汚い感じがしますが、それは私を助けてくれました...つまり、本質的に、同じことを行う4つのジョブを作成し、15秒間隔を空けました。の線に沿って:
...
new Thread(() =>
{
//loop from {id=1 through 4}
// create job here with {id} in the name at interval of 1 minute
// sleep 15 seconds
//end loop
}).Start();
...