Планирование заданий с высокой загрузкой процессора в Quartz.NET - PullRequest
3 голосов
/ 20 октября 2011

Я использую Quartz.NET для планирования задания, которое загружает кучу данных из внешних источников и сохраняется в базе данных. После их загрузки также необходимо выполнить некоторую обработку, которая создаст дополнительные записи в другой таблице в базе данных.

Задание загрузчика является заданием с состоянием и выполняется каждую минуту. Проблема, с которой я столкнулся, заключается в том, что после загрузки данных обработка может занять гораздо больше времени, чем я ожидал.

Как мне это сделать? Я думал о создании другой работы (которая будет выполняться только один раз), когда загрузка данных закончится. В этом случае задание загрузчика может запускаться каждую минуту (это был первоначальный план), поскольку загрузка занимает всего 5-20 секунд, а другое задание может обрабатывать эти записи после завершения загрузки. Задание обработчика получит записи, помеченные как необработанные, из базы данных и выполнит работу с ними.

Это правильный подход к обработке? Другая идея, которая пришла мне в голову, - создать службу WCF, которая будет обрабатывать один загруженный элемент. Это будет вызываться для каждого загруженного элемента. Однако я не думаю, что это будет работать лучше, чем другой подход к работе.

Ответы [ 3 ]

2 голосов
/ 31 января 2014

Может быть, лучше использовать задание как событие, а другой сервис выполнить загрузку.

Задание будет просто отправлять сообщение, определяющее намерение, другой конечной точке.

Это очень часто встречается в архитектуре, управляемой событиями, где используется брокер сообщений или служебная шина, например 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 голос
/ 18 июня 2012

Возможно, вы захотите настроить 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);, и дайте слушателю выполнить обработку после успешного выполнения задания.

1 голос
/ 20 октября 2011

Ваш подход к тому, чтобы задание на загрузку планировалось как другое задание для обработки, выполнимо и широко используется.

Однако следует иметь в виду, что это работает до тех пор, пока задание на загрузку не всегда запланирует задание на обработку. Если ваше задание на загрузку всегда назначает задание (скажем, каждую минуту), а запланированное задание занимает больше времени, чем это, вы в конечном итоге исчерпаете потоки обработки, и вашему заданию на загрузку придется ждать доступности потока.

...