重复作业同时执行多次

问题描述 投票:0回答:1

我有一个使用 HangFire 的 C# Worker,这里是 program.cs 设置:

 var sqliteOptions = new SQLiteStorageOptions();
    builder.Services.AddHangfire(configuration => configuration
    .UseSimpleAssemblyNameTypeSerializer()
    .UseRecommendedSerializerSettings()
    .UseFilter(new DisableConcurrentExecutionAttribute(300))
    .UseSQLiteStorage($"Filename={hangfireDbPath};" , sqliteOptions));

  builder.Services.AddHangfireServer(options =>
  {
      options.WorkerCount = 1; // Limit to one worker
  });

然后在 Worker.cs 中我有这个:

protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
    _fileMonitor.StartMonitoring();

    _logger.LogInformation("Backup service is starting.");

    // Start the Hangfire server
    using (var server = new BackgroundJobServer())
    {
        _backupService.ScheduleInitialJobs();

        _logger.LogInformation("Backup service has scheduled all initial backup jobs.");

        await Task.Delay(Timeout.Infinite, stoppingToken);
    }


}

我的备份服务有这个:

public void ScheduleInitialJobs()
{
    var backupPlans = _backupPlanService.GetAllBackupPlans();

    foreach (var plan in backupPlans)
    {
        if (plan.IsEnabled)
        {
            var cronExpression = GetCronExpression(plan);
            var options = new RecurringJobOptions
            {
                TimeZone = TimeZoneInfo.Local
            };
            try
            {
                _recurringJobManager.AddOrUpdate(
               plan.Name,
               () => ExecuteBackupAsync(plan, CancellationToken.None),
               cronExpression,
               options);

            }
            catch (Exception ex)
            {

            }
            
        }
    }
}

这是我的 ExecuteBackupAsync 方法:

 [MaximumConcurrentExecutions(1)]
 public async Task ExecuteBackupAsync(BackupPlan plan, CancellationToken cancellationToken)
 {
    ...
 }

我检查了日志文件,我可以看到:

2024-05-15 23:05:09.297 -06:00 [DBG] 1 recurring job(s) processed by scheduler.
2024-05-15 23:05:09.302 -06:00 [DBG] 1 recurring job(s) processed by scheduler.
2024-05-15 23:05:24.113 -06:00 [DBG] Server ava:90924:57316309 heartbeat successfully sent
2024-05-15 23:05:24.165 -06:00 [INF] Executing backup for plan: Plan01
2024-05-15 23:05:24.171 -06:00 [INF] Completed backup for plan: Plan01
2024-05-15 23:05:24.378 -06:00 [DBG] Server ava:90924:0204f2f5 heartbeat successfully sent
2024-05-15 23:05:24.381 -06:00 [INF] Executing backup for plan: Plan01
2024-05-15 23:05:24.382 -06:00 [INF] Completed backup for plan: Plan01
2024-05-15 23:05:24.386 -06:00 [INF] Executing backup for plan: Plan01
2024-05-15 23:05:24.387 -06:00 [INF] Completed backup for plan: Plan01
2024-05-15 23:05:24.400 -06:00 [INF] Executing backup for plan: Plan01
2024-05-15 23:05:24.401 -06:00 [INF] Completed backup for plan: Plan01
2024-05-15 23:05:24.403 -06:00 [INF] Executing backup for plan: Plan01
2024-05-15 23:05:24.404 -06:00 [INF] Completed backup for plan: Plan01
2024-05-15 23:05:24.419 -06:00 [INF] Executing backup for plan: Plan01
2024-05-15 23:05:24.420 -06:00 [INF] Completed backup for plan: Plan01
2024-05-15 23:05:24.587 -06:00 [INF] Executing backup for plan: Plan01
2024-05-15 23:05:24.588 -06:00 [INF] Completed backup for plan: Plan01
2024-05-15 23:05:24.590 -06:00 [INF] Executing backup for plan: Plan01
2024-05-15 23:05:24.591 -06:00 [INF] Completed backup for plan: Plan01
2024-05-15 23:05:24.594 -06:00 [INF] Executing backup for plan: Plan01
2024-05-15 23:05:24.595 -06:00 [INF] Completed backup for plan: Plan01
2024-05-15 23:05:24.601 -06:00 [INF] Executing backup for plan: Plan01
2024-05-15 23:05:24.602 -06:00 [INF] Completed backup for plan: Plan01
2024-05-15 23:05:54.125 -06:00 [DBG] Server ava:90924:57316309 heartbeat successfully sent
2024-05-15 23:05:54.387 -06:00 [DBG] Server ava:90924:0204f2f5 heartbeat successfully sent

这简直要了我的命,因为我可以确认只添加了一次 RecurringJob,并且我可以在 HangFire 数据库中检查这一点。

请帮忙!

c# hangfire
1个回答
0
投票

一些想法:

  1. 立即想到的是在该 catch 块中添加日志记录,以防失败
  2. 虽然日志显示已成功完成,但真的吗? 2 毫秒对于备份来说似乎很短(除非你的工作只是一个空方法 atm)
  3. 如果上述方法失败,那么 ExecuteBackupAsync 会“卡在”列表中的最后一个计划 (Plan01) 上,而实际上它会针对同一计划执行 N 次循环?由于 ExecuteBackupAsync 位于委托内部,因此它不会在循环时执行?
© www.soinside.com 2019 - 2024. All rights reserved.