在Quartz.NET中调度高CPU负载的作业

本文关键字:CPU 负载 作业 调度 Quartz NET | 更新日期: 2023-09-27 18:11:52

我用的是石英。. NET来调度一个作业,该作业从外部源加载一堆数据并保存在数据库中。在下载它们之后,还必须对它们进行一些处理,这将在数据库的另一个表中创建额外的记录。

downloader作业是一个有状态作业,每分钟运行一次。我遇到的问题是,在下载数据后,数据的处理部分可能比我预期的要长得多。

我该如何处理这个?我考虑过在数据下载完成时创建另一个作业(它将只运行一次)。在这种情况下,下载作业可以每分钟运行一次(这是原来的计划),因为下载部分只需要5-20秒,而其他作业可以在下载作业完成后处理这些记录。处理器作业将从数据库中获取标记为未处理的记录,并对它们进行处理。

这是处理处理的正确方法吗?我的另一个想法是建立一个WCF服务来处理一个下载的元素。这将在每个下载的元素上调用。然而,我不认为这将比其他工作方法执行得更好。

在Quartz.NET中调度高CPU负载的作业

也许更好的方法应该是将作业用作事件,并让另一个服务执行下载。

作业只会向另一个端点发送一个定义意图的消息。

这在带有某种消息代理或服务总线(如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);注册侦听器,并让侦听器在作业成功执行后进行处理。