且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

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

更新时间:2023-02-16 14:46:17

您是否看过 InvisibilityTimeout 设置 Hangfire文档


默认SQL Server作业存储实现使用常规表作为
a作业队列。为了确保在
意外进程终止的情况下不会丢失作业,成功完成时只会从队列中删除

Default SQL Server job storage implementation uses a regular table as a job queue. To be sure that a job will not be lost in case of unexpected process termination, it is deleted only from a queue only upon a successful completion.

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

To make it invisible from other workers, the UPDATE statement with OUTPUT clause is used to fetch a queued job and update the FetchedAt value (that signals for other workers that it was fetched) in an atomic way. Other workers see the fetched timestamp and ignore a job. But to handle the process termination, they will ignore a job only during a specified amount of time (defaults to 30 minutes).

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

Although this mechanism ensures that every job will be processed, sometimes it may cause either long retry latency or lead to multiple job execution. Consider the following scenario:


  1. 工人A获取一份工作(运行一小时)并在12:00开始工作。

  2. 工人B在12:30获取相同的工作,因为默认的隐身超时已过期。

  3. 工人C(没有获取)13的同一工作: 00,因为(成功演出后
    将被删除。)

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

If you are using cancellation tokens, it will be set for Worker A at 12:30, and at 13:00 for Worker B. This may lead to the fact that your long-running job will never be executed. If you aren’t using cancellation tokens, it will be concurrently executed by WorkerA and Worker B (since 12:30), but Worker C will not fetch it, because it will be deleted after successful performance.

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



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

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

截至 Hangfire 1.5此选项现在已过时 。正在处理的工作对其他工人是不可见的。

As of Hangfire 1.5 this option is now Obsolete. Jobs that are being worked on are invisible to other workers.


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

Say goodbye to confusing invisibility timeout with unexpected background job retries after 30 minutes (by default) when using SQL Server. New Hangfire.SqlServer implementation uses plain old transactions to fetch background jobs and hide them from other workers.

即使在非正常关闭之后,该作业也是如此将立即为其他
工作人员提供,不会有任何延迟。

Even after ungraceful shutdown, the job will be available for other workers instantly, without any delays.