分钟内的 Hangfire 重复任务

Hangfire recurring tasks under minute

有没有办法每隔几秒设置 hangfire 重复作业? 我不寻求一种即发即弃任务创建另一个即发即弃任务的解决方案,如果不是,建议的替代方案是什么?

Hangfire 不支持周期性作业的间隔小于一分钟。

为什么?想象一下,如果他们允许的时间少于一分钟:比如 1 秒。 hangfire 多久检查一次数据库中的重复作业?这会导致大量的数据库 IO。

有关 Hangfire 的详细信息,请参阅 this discussion

我遇到了同样的问题,这是我的解决方案:

private void TimingExecuteWrapper(Action action, int sleepSeconds, int intervalSeconds)
{
    DateTime beginTime = DateTime.UtcNow, endTime;
    var interval = TimeSpan.FromSeconds(intervalSeconds);
    while (true)
    {
        action();
        Thread.Sleep(TimeSpan.FromSeconds(sleepSeconds));
        endTime = DateTime.UtcNow;
        if (endTime - beginTime >= interval)
            break;
    }
}

intervalSeconds 是最小的 NCRON 间隔。 1分钟。 行动是我们的工作准则。 另外我建议使用 DisableConcurrentExecution 来避免一些并发冲突。

我认为任何反对允许少于 1 分钟的重复触发的人都是短视的。毕竟,55 秒的效率是否低于 1 分钟?好像很随意!尽管我很喜欢 Hangfire,但我遇到过这样的情况,我不得不将客户引导到 Quartz.net,仅仅是因为业务要求每 55 秒或类似时间 运行 的工作。

任何反驳说如果将其配置为每 1 秒 运行 会对性能产生严重影响的人再次对事物采取封闭的观点。当然,间隔为 1 秒的触发器可能不是一个好主意,但是对于不太可能有人会选择 1 秒的情况,我们是否禁止使用 55 秒或 45 秒?

无论如何,性能既是主观的,又取决于主机平台和硬件。在性能方面,API 真的不能强制执行意见。只需使轮询间隔和触发重复可配置即可。这样用户就可以为自己确定最佳结果。

虽然后台进程每 55 秒编排一个作业 运行 可能是一个选项,但它不是很令人满意。在这种情况下,通过 Hangfire UI 无法看到该进程,因此它对管理员是隐藏的。我觉得这种方法绕过了 Hangfire 的主要好处之一。

如果 Hangfire 是 Quartz.net 之类的有力竞争者,它至少会匹配它们的基本功能。如果 Quartz 可以支持间隔低于 1 分钟的触发器,那么为什么 Hangfire 不能呢!

尽管 Hangfire 不允许您安排少于一分钟的任务,但您实际上可以通过让函数递归地安排自己来实现这一点;也就是说,假设您希望每 2 秒触发一次某些方法,您可以安排一个在启动时调用该方法的后台作业;

BackgroundJob.Schedule(() => PublishMessage(), TimeSpan.FromMilliseconds(2000));

然后在您的 PublishMessage 方法中执行您的操作,然后安排一个作业来调用相同的方法;

public void PublishMessage()
    {
        /* do your stuff */

        //then schedule a job to exec the same method
        BackgroundJob.Schedule(() => PublishMessage(), TimeSpan.FromMilliseconds(2000));
    }

您需要覆盖的另一件事是默认的 SchedulePollingInterval 为 15 秒,否则您的方法只会在每 15 秒后被命中。为此,只需在启动时将 BackgroundJobServerOptions 的实例传递给 UseHangfireServer,就像这样;

var options = new BackgroundJobServerOptions
        {
            SchedulePollingInterval = TimeSpan.FromMilliseconds(2000)
        };

        app.UseHangfireServer(options);

我不知道我的解决方案如何 "foolproof",但我设法实现了我的目标并且一切都在 "happy" 生产中。

我有一个类似的要求,因为我有一个经常性的工作需要每 15 秒 运行。 我试图绕过这个限制所做的只是延迟计划作业的创建(设置为 1 分钟的间隔),这似乎可以解决问题。 然而,我发现,考虑到轮询间隔(将计划轮询间隔设置为我的频率)和选择新工作的延迟,这并不总是像它应该的那样准确,但目前正在做这个技巧.但是 better/proper 解决方案会很好。

觉得必须解决以下方法有点脏,但它帮助我解决了问题...... 所以本质上我创建了 4 个工作做同样的事情,创建间隔 15 秒。 沿着:

...

new Thread(() =>
{
    //loop from {id=1 through 4}
    //   create job here with {id} in the name at interval of 1 minute
    //   sleep 15 seconds
    //end loop
}).Start();    
...

不确定何时支持,但在 ASP.NET Core 2.0 和 Hangfire 1.7.0 中尝试过。以下代码每 20 秒安排一次作业:

RecurringJob.AddOrUpdate<SomeJob>(
    x => x.DoWork(),
    "*/20 * * * * *");

如果我没记错的话,由于 Hangfire 使用 NCrontab 允许使用 6 个令牌(第二粒度而不是分钟粒度)的 cron 表达式,因此支持 6 个令牌(而不是标准的 5 个令牌)。

Hangfire 仪表板也很好地显示了运行之间的小时间间隔:

我必须做同样的事情,但需要 5 秒。默认计划轮询间隔设置为 15 秒。所以它需要2个步骤来实现一个5s间隔的作业。

在Startup.cs

var options = new BackgroundJobServerOptions
{
    SchedulePollingInterval = TimeSpan.FromMilliseconds(5000)
};

app.UseHangfireDashboard();
app.UseHangfireServer(options);

你的工作

RecurringJob.AddOrUpdate(() => YourJob(), "*/5 * * * * *");