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

时间:2011-10-20 08:33:08

标签: c# wcf c#-4.0 scheduling quartz.net

我正在使用Quartz.NET来安排一个从外部源加载大量数据并在数据库中持久化的作业。下载后,必须对它们进行一些处理,这将在数据库的不同表中创建其他记录。

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

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

这是处理处理的正确方法吗?我的另一个想法是设置一个WCF服务,它将处理一个下载的元素。这将在每个下载的元素上调用。但是,我认为这不会比其他工作方法表现更好。

3 个答案:

答案 0 :(得分:2)

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

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

这在具有某种消息代理或服务总线的事件驱动架构中很常见,例如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.");
    }
}

答案 1 :(得分:1)

让下载作业安排另一个作业进行处理的方法是可行的并且通常使用。

要记住的一点是,只要下载作业并不总是安排处理作业,这就有效。如果您的下载作业总是安排一个作业(比如每分钟)并且预定的作业需要的时间比运行的时间长,那么最终将耗尽处理线程,并且您的下载作业将不得不等待一个线程可用。

答案 2 :(得分:1)

您可能会考虑为下载作业设置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);注册侦听器,让侦听器在作业成功执行后进行处理。