14

私は asp.net mvc-5 Web アプリケーションに取り組んでおり、Hangfire ツールを使用して実行時間の長いバックグラウンド ジョブを実行する際に問題に直面しています。問題は、ジョブの実行が 30 分を超えると、hangfire が自動的に別のジョブを開始するため、2 つの同様のジョブが同時に実行されることになります。

今、私は次のものを持っています:-

  1. Asp.net mvc-5
  2. IIS-8
  3. ハングファイア 1.4.6
  4. Windows サーバー 2012

これで、ハングファイアの繰り返しジョブを毎日 17:00 に実行するように定義しました。バックグラウンド ジョブは主にネットワークをスキャンしてサーバーと VM を探し、DB を更新します。定期的なジョブは実行完了後にメールを送信します。定期的なジョブは、実行が 30 分未満の場合にうまく機能していました。しかし、現在、システムが拡大するにつれて、定期的なジョブは以前の 22 ~ 25 分ではなく、40 分後に完了しました。そして、1通ではなく2通のメールを受け取りました(メール間の時間は約30分でした). ここで、ジョブを手動で再実行しましたが、問題は次のとおりであることに気付きました:-

「繰り返しジョブの連続実行が 30 分に達すると、繰り返しジョブの新しいインスタンスが開始されるため、同時に 1 つではなく 2 つのインスタンスが実行されるため、なぜ 2 つのメールを受信したのでしょうか。」

定期的なジョブの所要時間が 30 分未満 (たとえば 29 分) の場合、問題は発生しませんが、定期的なジョブの実行が 30 分を超えると、何らかの理由でハングファイアが発生し、新しいジョブが開始されます。ジョブの実行中に hangfire ダッシュボードにアクセスすると、アクティブなジョブが 1 つしかないことがわかりますが、DB を監視すると、DB にアクセスしている 2 つのジョブがあることが SQL プロファイラーからわかります。これは、繰り返しジョブの開始から 30 分後 (私たちの場合は 17:30) に発生し、2 つのメールを受信した理由は、1 つではなく 2 つの繰り返しジョブがバックグラウンドで実行されていることを意味します。

現在の定期的なジョブの実行が 30 分を超えた場合に、hangfire が新しい定期的なジョブを自動的に開始しないようにするにはどうすればよいですか? ありがとう

4

4 に答える 4

22

Hangfire docsInvisibilityTimeoutの設定を見ましたか?

デフォルトの SQL Server ジョブ ストレージの実装では、通常のテーブルがジョブ キューとして使用されます。プロセスが予期せず終了した場合にジョブが失われないようにするために、ジョブは正常に完了した場合にのみキューから削除されます。

他のワーカーから見えないようにするために、OUTPUT 句を含む UPDATE ステートメントを使用して、キューに入れられたジョブをフェッチし、FetchedAt 値 (フェッチされたことを他のワーカーに知らせる) をアトミックに更新します。他のワーカーは取得されたタイムスタンプを見て、ジョブを無視します。ただし、プロセスの終了を処理するために、指定された時間 (デフォルトは 30 分) の間だけジョブを無視します。

このメカニズムにより、すべてのジョブが確実に処理されますが、再試行の待ち時間が長くなったり、複数のジョブが実行されたりする場合があります。次のシナリオを検討してください。

  1. ワーカー A はジョブ (1 時間実行) を取得し、12:00 に開始しました。
  2. デフォルトの非表示タイムアウトが期限切れになったため、ワーカー B は同じジョブを 12:30 に取得しました。
  3. ワーカー C (取得しませんでした) は、13:00 に同じジョブを取得しました。これは、(正常に実行された後に削除されるためです。)

キャンセル トークンを使用している場合、ワーカー A には 12:30 に、ワーカー B には 13:00 に設定されます。これにより、実行時間の長いジョブが実行されない可能性があります。キャンセル トークンを使用していない場合、WorkerA と Worker B によって同時に実行されますが (12:30 以降)、正常に実行された後に削除されるため、Worker C はそれをフェッチしません。

したがって、実行時間の長いジョブがある場合は、非表示のタイムアウト間隔を構成することをお勧めします。

var options = new SqlServerStorageOptions
{
    InvisibilityTimeout = TimeSpan.FromMinutes(30) // default value
};

GlobalConfiguration.Configuration.UseSqlServerStorage("<name or connection string>", options);

Hangfire 1.5 以降、このオプションは になりObsoleteました。作業中のジョブは、他のワーカーには表示されません。

SQL Server の使用時に 30 分後 (デフォルト) にバックグラウンド ジョブが予期せず再試行され、混乱を招く非表示タイムアウトに別れを告げます。新しい Hangfire.SqlServer の実装では、単純な古いトランザクションを使用してバックグラウンド ジョブを取得し、他のワーカーから隠します。

予期せぬシャットダウンの後でも、ジョブは遅延なく即座に他のワーカーに利用可能になります。

于 2015-10-30T05:38:33.613 に答える
3

ただし、以下のことが述べられていることを指摘したいと思います。

Hangfire 1.5 以降、このオプションは廃止されました。作業中のジョブは、他のワーカーには表示されません。

SQL Server の使用時に 30 分後 (デフォルト) にバックグラウンド ジョブが予期せず再試行され、混乱を招く非表示タイムアウトに別れを告げます。新しいHangfire.SqlServer実装では、単純な古いトランザクションを使用してバックグラウンド ジョブを取得し、他のワーカーから隠します。

予期せぬシャットダウンの後でも、ジョブは遅延なく即座に他のワーカーに利用可能になります。

MySQL、PostgreSQL、MongoDB を使用している多くの人にとって、InvisibilityTimeoutまだ進むべき道のようです: https://github.com/HangfireIO/Hangfire/issues/1197

于 2019-09-05T09:59:55.633 に答える