【问题标题】:Hangfire recurring tasks under minute分钟内的 Hangfire 重复任务
【发布时间】:2016-07-14 06:54:11
【问题描述】:

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

【问题讨论】:

  • 关于this 文档,似乎不可能在第二个基础上创建重复任务。最小值为minutes

标签: c# .net hangfire


【解决方案1】:

不确定何时支持此功能,但在带有 Hangfire 1.7.0 的 ASP.NET Core 2.0 中进行了尝试。以下代码每 20 秒安排一次作业:

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

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

Hangfire 仪表板还可以很好地显示运行之间的小时间间隔:

【讨论】:

  • 如果你需要跑不到 15 秒,请设置 SchedulePollingInterval,正如 takaz 指出的那样。
  • 看起来这是在 1.7 或更高版本中添加的。好东西!!
【解决方案2】:

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

如果有人反驳说,如果将其配置为每 1 秒运行一次,将会对性能产生严重影响,那么他们再次对事情持封闭态度。当然,间隔为 1 秒的触发器可能不是一个好主意,但对于不太可能有人会选择 1 秒的情况,我们是否反对 55 秒或 45 秒?

在任何情况下,性能都是主观的,并且取决于主机平台和硬件。在性能方面,API 确实不能强制执行意见。只需使轮询间隔和触发重复可配置。这样用户就可以为自己确定最佳结果。

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

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

【讨论】:

【解决方案3】:

虽然 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);

我不知道我的解决方案有多“万无一失”,但我设法用它实现了我的目标,并且在生产中一切都很“快乐”。

【讨论】:

  • 问题中已经说明创建另一个任务的任务不是理想的答案。我想这在设计上是不可能的,就是这样
【解决方案4】:

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

在 Startup.cs 中

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

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

你的工作

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

【讨论】:

    【解决方案5】:

    Hangfire 不支持重复作业的间隔少于一分钟。

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

    有关更多信息,请参阅 Hangfire 上的 this discussion

    【讨论】:

    【解决方案6】:

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

    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 来避免一些并发冲突。

    【讨论】:

      【解决方案7】:

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

      不得不解决以下方法感到有点肮脏,但它帮助了我...... 所以本质上我创造了 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();    
      ...
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-03-04
        • 2022-08-16
        • 1970-01-01
        • 2020-04-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多