【发布时间】:2016-07-14 06:54:11
【问题描述】:
有没有办法每隔几秒设置一次挂火重复作业? 我不寻求一种解决方案,即“即火即忘”任务会创建另一个“即火即忘”任务,如果没有,建议的替代方案是什么?
【问题讨论】:
有没有办法每隔几秒设置一次挂火重复作业? 我不寻求一种解决方案,即“即火即忘”任务会创建另一个“即火即忘”任务,如果没有,建议的替代方案是什么?
【问题讨论】:
不确定何时支持此功能,但在带有 Hangfire 1.7.0 的 ASP.NET Core 2.0 中进行了尝试。以下代码每 20 秒安排一次作业:
RecurringJob.AddOrUpdate<SomeJob>(
x => x.DoWork(),
"*/20 * * * * *");
如果我没记错的话,由于 Hangfire 使用 NCrontab 支持 6 个令牌(而不是标准的 5 个令牌),它允许具有 6 个令牌(第二粒度而不是分钟粒度)的 cron 表达式。
Hangfire 仪表板还可以很好地显示运行之间的小时间间隔:
【讨论】:
SchedulePollingInterval,正如 takaz 指出的那样。
我认为任何反对允许少于 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);
我不知道我的解决方案有多“万无一失”,但我设法用它实现了我的目标,并且在生产中一切都很“快乐”。
【讨论】:
我必须做同样的事情,但需要 5 秒。默认计划轮询间隔设置为 15 秒。所以它需要2个步骤来实现一个5s的间隔作业。
在 Startup.cs 中
var options = new BackgroundJobServerOptions
{
SchedulePollingInterval = TimeSpan.FromMilliseconds(5000)
};
app.UseHangfireDashboard();
app.UseHangfireServer(options);
你的工作
RecurringJob.AddOrUpdate(() => YourJob(), "*/5 * * * * *");
【讨论】:
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 来避免一些并发冲突。
【讨论】:
我有一个类似的要求,因为我有一个需要每 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();
...
【讨论】: