替代轮询作业调度程序

Posted

技术标签:

【中文标题】替代轮询作业调度程序【英文标题】:Alternative to polling for job scheduler 【发布时间】:2011-06-06 19:43:06 【问题描述】:

我们在工作中需要一个工作服务器,我目前正在玩 Quartz.net,但创建自己的想法对我很有吸引力。至少了解 Quartz.net 可能在幕后做的事情不会损害我更有效地使用它的理解/机会。

所以我的问题是,如果没有轮询,您将如何在线程上获取和解雇工作?如果您每 2 分钟检查一次“工作商店”以查找需要解雇的工作,您可能会延迟大约 2 分钟。如果您减少轮询时间,则会增加您的工作商店的压力,并且仍然无法获得真正的开始时间。您可以在接下来的两分钟内预加载作业,并让线程在剩余时间内进入睡眠状态,以便它们在适当的时间开始,但如果您的轮询时间很长(删除、重新安排等),这似乎很笨拙并且容易出现问题。我正在剖析 Quartz 以弄清楚它是如何做到的,但我想知道我是否遗漏了一些基本的东西。

编辑:

像 Kevin 最初描述的线程结构似乎是你应该如何做一个工作服务器。它以最少的开销为您提供最大的灵活性。因为线程对于大多数人来说都是一个皮塔(也许只有我 :) 更简单的轮询示例将在 90% 的情况下完成工作,但代价是失去灵活性和更多开销。

另一方面,除非您将其设为单线程并执行单个作业,否则无论如何您都必须处理线程。还不如全力以赴,弄清楚信号。

我也同意 Kevin 的观点,即您在投票数据库示例中声称免费获得的东西并不是真正免费的。如果它是线程/等待应用程序,您将像编写代码一样编写代码。如果您的轮询数据库作业服务器在作业过程中发生故障怎么办?两者都将依赖一些持久的存储来跟踪他们的状态以防发生灾难。

如果您将“jobstore”提升到一个抽象级别并且它不是基于正常的 ACID(正确的术语?)数据库,该怎么办。现在我相信你的很多“免费”东西都不再可用(交易?)。

【问题讨论】:

根据我的经验,每秒轮询一次“作业存储”(对我来说是数据库中的一个表)表示我的数据库上的负载非常小。你会得到 1 秒的最大延迟,这似乎是可以容忍的。 是的,我感觉它是那些非问题问题之一,但我很好奇,所以我想我会问。 【参考方案1】:

您将创建一个要触发的任务队列,按时间排序(从最短到最长的时间)。将只有一个线程在队列的头部等待时间。当该时间到期时,您删除该项目并启动该任务。如果是重复任务,则重新计算并放回队列中。

唯一棘手的事情是线程应该根据一些条件变量等待。如果队列头发生变化,则可以向条件变量发出信号。通常使用条件变量,您可以判断它是否已发出信号与超时过期。因此,如果收到信号,您只需重新等待新的头部时间,否则超时表明是时候在队列头部运行任务了。

此解决方案意味着您只有一个线程来管理任务,它不是轮询。

编辑:

我将更新我的解决方案,指出编写自己的调度程序可能不是一个好主意,因为石英是一个非常好的解决方案。此外,我认为每秒轮询有点过头了,因为作业通常是按分钟运行,而不是按每秒运行。例如,您是否真的关心工作是否从 12:00:05 开始,或者 12:00:00 是否足够好?无论如何,您都可以参数化您的轮询以满足所需的粒度级别。

【讨论】:

只有我的大脑。我曾经在一家从事企业工作调度的公司工作。 @Thomas Li:如果你愿意,我可以在回答中提供更多细节。 是的,如果您能提供更多详细信息,那就太好了。我认为我最大的问题是在线程和信号/警报/计时器/中断方面的新手状态 与标准的面向数据库的解决方案相比,该解决方案的鲁棒性(如果服务器重新启动会发生什么?)和可扩展性(当您想在多台机器之间共享工作负载时会发生什么?)让我印象深刻。 @Kirk Woll:很明显,在启动时,您将从数据库表中读取条目。您需要从表中控制插入/删除(通过 api),以便将插入/删除的列传播到内存数据结构中。

以上是关于替代轮询作业调度程序的主要内容,如果未能解决你的问题,请参考以下文章

cron 如何在内部调度作业?

Round Robin 轮询调度算法

作业调度—了解

如何检查是不是在 Firebase 作业调度程序中安排了作业?

使用 firebase 作业调度程序安排重复作业

在操作系统中,啥是进程的作业调度,交换调度和进程调度?