在Quartz.NET中调度高CPU负载的作业
本文关键字:CPU 负载 作业 调度 Quartz NET | 更新日期: 2023-09-27 18:11:52
我用的是石英。. NET来调度一个作业,该作业从外部源加载一堆数据并保存在数据库中。在下载它们之后,还必须对它们进行一些处理,这将在数据库的另一个表中创建额外的记录。
downloader作业是一个有状态作业,每分钟运行一次。我遇到的问题是,在下载数据后,数据的处理部分可能比我预期的要长得多。
我该如何处理这个?我考虑过在数据下载完成时创建另一个作业(它将只运行一次)。在这种情况下,下载作业可以每分钟运行一次(这是原来的计划),因为下载部分只需要5-20秒,而其他作业可以在下载作业完成后处理这些记录。处理器作业将从数据库中获取标记为未处理的记录,并对它们进行处理。
这是处理处理的正确方法吗?我的另一个想法是建立一个WCF服务来处理一个下载的元素。这将在每个下载的元素上调用。然而,我不认为这将比其他工作方法执行得更好。
也许更好的方法应该是将作业用作事件,并让另一个服务执行下载。
作业只会向另一个端点发送一个定义意图的消息。
这在带有某种消息代理或服务总线(如NServiceBus或MassTransit)的事件驱动架构中非常常见。
这样你的调度程序将保持精简和可伸缩。
下面是一个例子:
public class DownloadFileJob : IJob
{
public IBus Bus { get; set; }
public ILogger Logger{ get; set; }
public void Execute(IJobExecutionContext context)
{
Bus.Send(new DownloadFileMessage());
Logger.Info("Sending message requesting download of file.");
}
}
让下载作业调度另一个作业来进行处理的方法是可行的,并且通常被使用。
有一件事要记住,只要下载作业不总是调度处理作业,这就可以工作。如果您的下载作业总是调度一个作业(比如每分钟调度一次),并且调度的作业需要的时间超过这个时间才能运行,那么您最终将耗尽处理线程,并且您的下载作业将不得不等待一个线程可用。
您可以考虑为下载作业设置一个JobListener
。只需创建一个实现IJobListener
接口的类,然后将处理代码放在JobWasExecuted
方法中:
public PostDownloadJobListener : IJobListener
{
string Name { get { return "MyJobListener"; } }
void JobToBeExecuted(JobExecutionContext context) { }
void JobExecutionVetoed(JobExecutionContext context) { }
void JobWasExecuted(JobExecutionContext context, JobExecutionException jobException)
{
// Perform processing here
}
}
使用scheduler.AddJobListener(myJobListener);
注册侦听器,并让侦听器在作业成功执行后进行处理。