как избежать тайм-аута при длительном выполнении метода

Я работаю над веб-приложением asp.net mvc 5, развернутым внутри IIS-8, и у меня есть метод внутри моего приложения для выполнения длительной задачи, которая в основном сканирует нашу сеть на наличие серверов и виртуальных машин и обновляет нашу базу данных с результатами сканирования . выполнение метода может длиться от 30 до 40 минут в производственной среде. и я использую инструмент расписания под названием Hangfire, который будет вызывать этот метод 2 раза в день.

вот определение задания в файле startup.cs, которое вызовет метод в 8:01 am & _2 _: -

public void Configuration(IAppBuilder app)
{
    var options = new SqlServerStorageOptions
    {
        PrepareSchemaIfNecessary = false
    };
    GlobalConfiguration.Configuration.UseSqlServerStorage("scanservice",options);

    RecurringJob.AddOrUpdate(() => ss.Scan(), "01 8,20 ***");
}

и вот метод, который вызывается дважды в день инструментом расписания: -

public void Scan()
{
    Service ss = new Service();
    ss.NetworkScan().Wait();
}

Наконец, метод, который выполняет настоящее сканирование, (я предоставляю только высокоуровневое описание того, что будет делать метод): -

public async Task<ScanResult> NetworkScan()
{
    // retrieve the server info from the DB
    // loop over all servers & then execute some power shell commands to scan the network & retrieve the info for each server one by one...
    // after the shell command completed for each server, i will update the related server info inside the DB 

в настоящее время я провел несколько тестов в нашей тестовой среде, и все работало хорошо, где сканирование заняло около 25 секунд, чтобы сканировать 2 тестовых сервера. но теперь мы планируем перенести приложение в производство, и у нас есть около 120 ++ серверов для сканирования . поэтому я оцениваю, что выполнение метода в производственной среде займет около 30-40 минут. Итак, мой вопрос в том, как я могу убедиться, что это выполнение никогда не истечет, а метод ScanNetwork () завершится до конца?


person john Gu    schedule 02.10.2015    source источник
comment
Разве он не должен работать до тех пор, пока он не будет выполнен, или пока не возникнет ошибка, которая приведет к преждевременному возврату?   -  person Dylan    schedule 02.10.2015
comment
@ Дилан, можешь рассказать подробнее, что ты имеешь в виду? я хочу быть уверенным, что срок действия операции никогда не истечет, если она будет длиться 30-40 минут?   -  person john Gu    schedule 02.10.2015
comment
Почему вы беспокоитесь о том, что время ожидания метода истечет? Он должен работать до тех пор, пока метод не будет выполнен, или пока не возникнет проблема и не завершится. Я не верю, что у метода есть временные ограничения.   -  person Dylan    schedule 02.10.2015
comment
@Dylan, но я предполагал, что поток IIS будет отключен через определенное время   -  person john Gu    schedule 02.10.2015
comment
По умолчанию время ожидания пула приложений составляет 20 минут. Вы можете изменить его в расширенных настройках в пуле приложений, который вы используете. Служба Windows может быть лучше для этого, поэтому вам не нужно беспокоиться о ее истечении времени. Черт возьми, вы могли бы сделать это в консольном приложении и запустить его из планировщика заданий.   -  person Dylan    schedule 02.10.2015
comment
Дилан прав. Если вы запускаете что-то подобное в контексте веб-сервера - не делайте этого. Если веб-сайт должен запускать что-то подобное, создайте приложение конечной точки и запустите его из веб-приложения. Похоже, ваш сайт даже не отслеживает отзывы. Если ваш веб-сайт отслеживает результаты сканирования, просто напишите где-нибудь обновления и заставьте веб-сайт периодически получать их. Или используйте SignalR для обратной связи   -  person T.S.    schedule 03.10.2015
comment
Увеличьте также SqlServerOptions.InvisibilityTimeout (по умолчанию до 30 минут) или просто обновите до Hangfire 1.5.0 (я удалил этот тайм-аут), чтобы другие работники не получали то же фоновое задание после тайм-аута.   -  person odinserj    schedule 03.10.2015
comment
Также подумайте о том, чтобы использовать параметр IJobCancellationToken (или просто CancellationToken и его метод ThrowIfCancellationRequested, если вы обновляетесь до 1.5.0) и передать его вашему NetworkScan методу, чтобы иметь возможность отменить сканирование при завершении работы приложения и предотвратить тайм-ауты завершения работы.   -  person odinserj    schedule 03.10.2015
comment
@odinserj Я использую Hangfire 1.4.6, и я думаю, что он справится с управлением выключением, но мой вопрос в том, как я могу избежать тайм-аута во время выполнения метода ... я понимаю, что я хочу сказать.   -  person john Gu    schedule 03.10.2015
comment
@ Т. Я знаю, что выполнение этого внутри веб-приложения может быть не на 100% надежным решением, но мой вопрос был в том, как я могу это улучшить? и с какими проблемами я столкнусь, если продолжу выполнять этот длительный процесс из веб-приложения ..   -  person john Gu    schedule 03.10.2015
comment
Это ответ - проблема в том, что вы берете ресурсы из своего веб-приложения, оставляя ему меньше ресурсов и потенциально замедляя его. Тайм-аут, о котором вы говорите, не произойдет, если, скажем, вы запустите процесс в веб-контексте в отдельном потоке - он будет выполняться до конца, пока поток не остановится.   -  person T.S.    schedule 03.10.2015
comment
@ Т. спасибо за ответ, значит, вы имеете в виду, что процесс веб-контекста запустит его до конца, даже если тайм-аут пула приложений установлен на 20 минут? я не понял твою точку зрения? не могли бы вы рассказать об этом подробнее?   -  person john Gu    schedule 04.10.2015
comment
Вы, наверное, говорите о тайм-ауте простоя. Но ваша ветка не простаивает. Этот тайм-аут удаляет только бездействующих рабочих. Ваш рабочий будет активен.   -  person T.S.    schedule 04.10.2015
comment
@ Т. но я всегда читаю, что выполнение длительного процесса внутри IIS может вызвать тайм-ауты, поэтому не уверен, почему в моем случае я не получу тайм-аутов?   -  person john Gu    schedule 05.10.2015
comment
Опять же, если у вас есть запрос и до получения ответа вы выполняете долгую работу - это может вызвать тайм-аут. Но если вы немедленно отправите ответ и запустите свое долгое задание в фоновом потоке - в этом случае ваш поток завершится без тайм-аута.   -  person T.S.    schedule 05.10.2015
comment
@ Т. спасибо за ответ, но не могли бы вы посоветовать, что вы имеете в виду под «Но если вы отправите ответ немедленно». ,,,, что вы имеете в виду, говоря «отправить ответ немедленно»?   -  person john Gu    schedule 06.10.2015
comment
Вы находитесь на веб-сервере. Суть его в том, что он получает запрос и отправляет ответ. Если ваш запрос требует длительной работы, вы можете получить web request timed out. Итак, в этих случаях вы начинаете обрабатывать длительное задание в фоновом потоке, а затем отправляете ответ обратно. Это приведет к тому, что ответ будет отправлен клиенту во время процесса LRJ.   -  person T.S.    schedule 06.10.2015


Ответы (1)


Вместо того, чтобы беспокоиться о тайм-ауте вашей задачи, возможно, вы могли бы запустить новую задачу для каждого сервера. Таким образом, каждая задача будет очень недолговечной, и любые исключения, вызванные сканированием одного сервера, не повлияют на все остальные. Кроме того, если ваше приложение будет перезапущено в IIS, любые проверки, которые еще не были завершены, будут возобновлены. Это невозможно, если все сканирование выполняется в одной последовательной задаче. Скорее всего, вы также увидите, что общее время для завершения сканирования всей вашей сети резко упало, поскольку большая часть времени, вероятно, будет потрачена на ожидание на удаленных серверах.

public void Scan()
{
    Service ss = new Service();
    foreach (var server in ss.GetServers())
    {
        BackgroundJob.Enqueue<Service>(s => s.ServerScan(server));
    }
}

Теперь ваша запланированная задача просто поставит в очередь по одной новой задаче для каждого сервера.

person Austin Morton    schedule 07.10.2015