如何防止Hangfire定期作业在连续执行30分钟后重新启动

时间:2015-10-30 00:33:19

标签: asp.net iis asp.net-mvc-5 background-process hangfire

我正在开发一个asp.net mvc-5 Web应用程序,我在使用Hangfire工具运行长时间运行的后台作业时遇到了问题。 问题是,如果作业执行时间超过30分钟,那么hangfire将自动启动另一个作业,因此我最终会同时运行两个类似的作业。

现在我有以下内容: -

  1. Asp.net mvc-5
  2. IIS-8
  3. Hangfire 1.4.6
  4. Windows server 2012
  5. 现在我已经定义了一个每天17:00运行的篝火重复工作。后台作业主要扫描我们的网络中的服务器和虚拟机并更新数据库,定期作业将在完成执行后发送电子邮件。 经常性工作在执行时间不到30分钟时效果很好。但是今天随着我们的系统的发展,经常性的工作在40分钟后完成,而不是像过去那样在22-25分钟之后完成。我收到了2封电子邮件,而不是一封电子邮件(电子邮件之间的时间约为30分钟)。现在我手动重新运行这个工作,我注意到问题如下: -

      

    “当经常性工作连续执行30分钟时,a   定期工作的新实例将开始,所以我将有两个   实例而不是同时运行的实例,这就是我收到2封电子邮件的原因。“

    现在,如果定期工作不到30分钟(例如29分钟),我将不会遇到任何问题,但如果定期执行的工作超过30分钟,那么由于某种原因或其他原因,将启动一项新工作。 虽然当我在执行作业期间访问hangfire仪表板时,我发现只有一个活动作业,当我监视我的数据库时,我可以从sql profiler看到有两个作业访问数据库。这种情况发生在经常性工作开始30分钟后(在我们的案例中为17:30),这就是为什么我收到2封电子邮件,这意味着2个重复工作在后台运行而不是一个。

    所以有人可以提出这方面的建议吗,如果目前的重复工作执行时间超过30分钟,我怎么能避免因自动启动新的定期工作而引发的篝火? 谢谢

4 个答案:

答案 0 :(得分:14)

您是否从Hangfire docs了解了InvisibilityTimeout设置?

  

默认SQL Server作业存储实现使用常规表作为   一份工作队列。为了确保工作不会丢失,以防万一   意外的进程终止,它仅从队列中删除   成功完成后。

     

要使其与其他worker不可见,请使用UPDATE语句   OUTPUT子句用于获取排队作业并更新FetchedAt   价值(表明其获取的其他工人的信号)   原子方式。其他工作人员看到获取的时间戳并忽略了工作。   但是为了处理流程终止,他们只会忽略一份工作   在指定的时间内(默认为30分钟)。

     

虽然这种机制可以确保每个作业都得到处理,   有时它可能会导致长时间的重试延迟或导致多次   工作执行。请考虑以下情形:

     
      
  1. 工人A取了一份工作(运行了一个小时)并在12:00开始工作。
  2.   
  3. 工作人员B在12:30获取相同的工作,因为默认的不可见超时已过期。
  4.   
  5. 工人C(没有取得)同样的工作在13:00,因为(它   成功演出后将被删除。)
  6.         

    如果您使用取消令牌,则将为工人A设置   工人B的12:30和13:00。这可能导致你的事实   长期工作永远不会被执行。如果你不使用   取消令牌,它将由WorkerA和   工人B(从12:30开始),但是工人C不会拿它,因为它   成功演出后将被删除。

         

    因此,如果您有长时间运行的作业,最好配置   隐身超时间隔:

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

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

截至Hangfire 1.5 this option is now Obsolete。正在处理的工作对其他工人来说是不可见的。

  

告别将隐身超时与意外混淆   使用SQL时,在30分钟后(默认情况下)后台作业重试   服务器。新的Hangfire.SqlServer实现使用普通的旧版本   用于获取后台作业并将其隐藏在其他作业中的事务   工人。

     

即使在非正常关机后,该工作也可供其他人使用   工人们立即,没有任何延误。

答案 1 :(得分:5)

我在查找有关如何正确配置Postgresql数据库的文档时遇到了麻烦,我看到的每个示例都在使用sqlserver,我发现隐形超时是PostgreSqlStorageOptions对象内部的一个属性,我在这里找到了:{{ 3}}。幸运的是,通过反复试验,我能够确定UsePostgreSqlStorage有一个重载来接受该对象。对于.Net Core 2.0,当您在启动类的ConfigureServices方法中设置hangfire postgresql DB时,添加以下内容(默认超时设置为30分钟):

mm.astype(int)

答案 2 :(得分:0)

在使用Hangfire.MemoryStorage作为存储提供程序时遇到了这个问题。使用内存存储时,您需要在FetchNextJobTimeout中设置MemoryStorageOptions,否则默认情况下作业将在30分钟后超时并执行新的作业。

var options = new MemoryStorageOptions
{
    FetchNextJobTimeout = TimeSpan.FromDays(1)
};
GlobalConfiguration.Configuration.UseMemoryStorage(options);

答案 3 :(得分:0)

仅想指出一点,即使在下面的thing中指出:

  

截至Hangfire 1.5 this option is now Obsolete。其他工人看不到正在处理的工作。

     

告别使用SQL Server时30分钟(默认情况下)后30分钟(默认情况下)后,隐身超时与意外的后台作业重试混淆了。新的Hangfire.SqlServer实现使用普通的旧事务来获取后台作业并将其对其他工作人员隐藏。

     

即使不愉快地关闭后,该工作也将立即可供其他工人使用,而不会出现任何延迟。

对于许多使用MySQL,PostgreSQL,MongoDB的人来说,InvisibilityTimeout仍然是走的路:https://github.com/HangfireIO/Hangfire/issues/1197