我正在使用Quartz.NET来安排一个从外部源加载大量数据并在数据库中持久化的作业。下载后,必须对它们进行一些处理,这将在数据库的不同表中创建其他记录。
下载程序作业是一项有状态的工作,每分钟运行一次。我遇到的问题是,在下载数据后,处理部分的处理时间可能比我预期的要长得多。
我该如何管理?我在创建另一份工作(仅运行一次)时,数据下载完成了。在这种情况下,下载程序作业可以在每分钟运行(这是原始计划),因为下载部分仅需要5-20秒,而另一个作业可以在下载程序完成后处理这些记录。处理程序作业将从数据库中获取标记为未处理的记录,并对其进行处理。
这是处理处理的正确方法吗?我的另一个想法是设置一个WCF服务,它将处理一个下载的元素。这将在每个下载的元素上调用。但是,我认为这不会比其他工作方法表现更好。
答案 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);
注册侦听器,让侦听器在作业成功执行后进行处理。