joh*_* Gu 8 asp.net iis background-process asp.net-mvc-5 hangfire
我正在使用asp.net mvc-5 Web应用程序,我在使用Hangfire工具运行长时间运行的后台作业时遇到了问题.问题是如果作业执行超过30分钟,那么hangfire会自动启动另一个作业,所以我最终会同时运行两个类似的作业.
现在我有以下内容: -
现在我已经定义了一个每天17:00运行的篝火重复工作.后台作业主要扫描我们的网络中的服务器和虚拟机并更新数据库,定期作业将在完成执行后发送电子邮件.经常性工作在执行时间不到30分钟时效果很好.但是今天随着我们的系统的发展,经常性的工作在40分钟后完成,而不是像过去那样在22-25分钟之后完成.我收到了2封电子邮件,而不是一封电子邮件(电子邮件之间的时间约为30分钟).现在我手动重新运行这个工作,我注意到问题如下: -
"当定期作业达到30分钟连续执行时,定期作业的新实例将启动,因此我将有两个实例而不是同时运行的实例,这就是我收到2封电子邮件的原因."
现在,如果定期工作不到30分钟(例如29分钟),我将不会遇到任何问题,但如果重复执行的工作超过30分钟,那么由于某种原因或其他原因,将启动新工作.虽然当我在执行作业期间访问hangfire仪表板时,我发现只有一个活动作业,当我监视我的数据库时,我可以从sql profiler看到有两个作业访问数据库.这种情况发生在经常性工作开始30分钟后(在我们的案例中是17:30),这就是为什么我收到2封电子邮件,这意味着2个重复工作在后台运行而不是一个.
那么有人可以提出这方面的建议吗,如果目前的重复工作执行时间超过30分钟,我怎么能避免因自动启动新的定期工作而导致绞火?谢谢
Sho*_*hoe 18
您是否看过Hangfire文档中的InvisibilityTimeout设置?
默认SQL Server作业存储实现使用常规表作为作业队列.为了确保在意外的进程终止时不会丢失作业,只有在成功完成后才会从队列中删除它.
为了使其与其他工作者不可见,带有OUTPUT子句的UPDATE语句用于获取排队的作业并以原子方式更新FetchedAt值(为其他工作者发出信号).其他工作人员看到获取的时间戳并忽略了工作.但是为了处理进程终止,他们将仅在指定的时间内(默认为30分钟)忽略作业.
尽管此机制可确保处理每个作业,但有时可能会导致重试延迟时间过长或导致多个作业执行.请考虑以下情形:
- 工人A找到一份工作(运行一小时)并在12:00开始工作.
- 工作人员B在12:30获取相同的工作,因为默认的不可见性超时已过期.
- 13:00工作者C(没有获取)相同的工作,因为(成功执行后它将被删除.)
如果您使用取消令牌,则将在12:30为工人A设置,为工人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);
Run Code Online (Sandbox Code Playgroud)
截至Hangfire 1.5,此选项现已开始实施Obsolete.正在进行的工作对其他工人来说是不可见的.
在使用SQL Server 30分钟(默认情况下)后,告别将隐身超时与意外的后台作业重试混淆.新的Hangfire.SqlServer实现使用普通旧事务来获取后台作业并将其隐藏在其他工作者之外.
即使在非正常关机后,该工作也会立即为其他工作人员提供,不会有任何延误.
我无法找到有关如何正确地为Postgresql数据库执行此操作的文档,我看到的每个示例都使用sqlserver,我发现隐身超时是PostgreSqlStorageOptions对象中的属性,我在此处找到:https:// github .com/frankhommers/Hangfire.PostgreSql/blob/master/src/Hangfire.PostgreSql/PostgreSqlStorageOptions.cs#L36.幸运的是,通过反复试验,我能够发现UsePostgreSqlStorage有一个重载来接受这个对象.对于.Net Core 2.0,当您在启动类的ConfigureServices方法中设置hangfire postgresql DB时添加此项(默认超时设置为30分钟):
services.AddHangfire(config =>
config.UsePostgreSqlStorage(Configuration.GetConnectionString("Hangfire1ConnectionString"), new PostgreSqlStorageOptions {
InvisibilityTimeout = TimeSpan.FromMinutes(720)
}));
Run Code Online (Sandbox Code Playgroud)
只是想指出,尽管如此,还是有以下几点说明:
从 Hangfire 1.5开始,此选项现已过时。其他工人看不到正在从事的工作。
使用 SQL Server 时,告别令人困惑的不可见超时和 30 分钟(默认情况下)后意外的后台作业重试。新的
Hangfire.SqlServer实现使用普通的旧事务来获取后台作业并对其他工作人员隐藏它们。即使在非正常关闭之后,其他工人也可以立即完成这项工作,不会有任何延误。
似乎对于许多使用 MySQL、PostgreSQL、MongoDB 的人来说,InvisibilityTimeout仍然是要走的路: https: //github.com/HangfireIO/Hangfire/issues/1197
我在使用 Hangfire.MemoryStorage 作为存储提供程序时遇到了这个问题。随着记忆存储你需要设置FetchNextJobTimeout的MemoryStorageOptions,否则默认工作将在30分钟后超时和新的工作将被执行。
var options = new MemoryStorageOptions
{
FetchNextJobTimeout = TimeSpan.FromDays(1)
};
GlobalConfiguration.Configuration.UseMemoryStorage(options);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
7390 次 |
| 最近记录: |