Лучший способ запустить запланированные задачи [закрыто]


229

Сегодня мы создали консольное приложение для запуска запланированных задач для нашего веб-сайта ASP.NET. Но я думаю, что этот подход немного подвержен ошибкам и его трудно поддерживать. Как выполнить запланированное задание (в среде Windows / IIS / ASP.NET)

Обновить:

Примеры задач:

  • Отправка электронной почты из почтовой очереди в базе данных
  • Удаление устаревших объектов из базы данных
  • Получение статистики из Google AdWords и заполнение таблицы в базе данных.

Какой пример задач, которые вы выполняете?
JeffO

4
Вам нужно проверить atrigger.com
Kousha

Если у вас есть Plesk, вы можете написать VBS и
объявить

Ответы:


74

Все мои задачи (которые должны быть запланированы) для веб-сайта хранятся на веб-сайте и вызываются со специальной страницы. Затем я написал простой сервис Windows, который вызывает эту страницу очень часто. Когда страница запускается, она возвращает значение. Если я знаю, что нужно проделать еще больше работы, я сразу же запускаю страницу, в противном случае я запускаю ее через некоторое время. Это сработало очень хорошо для меня и сохраняет всю мою логику задач с веб-кодом. Перед написанием простой службы Windows я использовал планировщик Windows для вызова страницы каждые х минут.

Другой удобный способ запустить это - использовать сервис мониторинга, такой как Pingdom . Направьте их проверку http на страницу, которая запускает ваш сервисный код. Попросите страницу вернуть результаты, которые затем можно использовать для запуска Pingdom для отправки предупреждений, когда что-то не так.


3
Это решение, которое я закончил. Вместо пользовательского веб-сервиса я использую планировщик windows + curl. В чем выгода от использования службы Windows.
Нильс Босма

16
Вы смотрели на технику истечения срока действия Cache Item? Я думаю, вы обнаружите, что это гораздо более идеальная реализация запланированного сервиса: codeproject.com/KB/aspnet/ASPNETService.aspx
Ричард Клейтон

10
Что мешает злоумышленнику (или пауку поисковой системы) вызвать эту страницу и, таким образом, запустить запланированные задачи?
UpTheCreek

8
Вы можете остановить злонамеренные вызовы, сохранив статическую метку времени в веб-приложении и запустив ее только в том случае, если метка времени не была установлена ​​(первый вызов) или истекло правильное время с момента последнего вызова.
Роб Кент

5
Я прекращаю злонамеренные вызовы на свой URL, проверяя, является ли IP-адрес внутренним адресом или нет. Он ничего не возвращает и ничего не делает, если он не является внутренним для нашей организации.
user1408767

128

Эта техника Джеффа Этвуда для Stackoverflow - самый простой метод, с которым я столкнулся. Он опирается на механизм обратного вызова «элемент кэша удален», встроенный в систему кэширования ASP.NET.

Обновление: Stackoverflow перерос этот метод. Он работает только во время работы сайта, но это очень простая техника, которая полезна для многих людей.

Также проверьте Quartz.NET


12
Так что же произойдет, если приложение не запущено, но запланированное задание должно произойти?
MichaelGG

2
Это также может замедлить работу пользователя, если на этот раз задача займет некоторое время. Я предпочитаю, чтобы пользователь не порождал для меня свое обслуживание / задачи.
Бретцки

5
Это чертовски страшно! Что-нибудь может привести к тому, что приложение перестанет работать, и оно, вероятно, будет перезапущено только при следующем запросе пользователя. Между тем ваши задачи не запускаются!
teedyay

43
Кое-что я заметил сегодня в комментариях к оригинальному сообщению в блоге: No, we’ve switched to a dedicated task. We definitely outgrew this technique. I do think it’s fine for small sites though!- Джефф Этвуд
Джоэл Кохорн

3
-1 В этом подходе есть большой недостаток. Всякий раз, когда приложение перезапускается, возникает событие CacheItemRemoved, и запускается запланированное задание. На производственных площадках это может происходить несколько раз в день. Не очень хорошо, если вы хотите, чтобы задача выполнялась еженедельно.
Стивен де Салас

30

Создайте пользовательскую службу Windows .

У меня были некоторые критически важные задачи, настроенные как запланированные консольные приложения, и мне было трудно их поддерживать. Я создал службу Windows с «пульсом», который проверял расписание в моей БД каждые пару минут. Это сработало очень хорошо.

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


7
К вашему сведению, ссылка сейчас мертва.
Чарльз Бернс

1
@CharlesBurns, вы всегда можете просмотреть неработающие ссылки с archive.org: web.archive.org/web/20090919131944/http://www.dotheweb.net/…
Николай Костов

17

Я обнаружил, что это легко для всех участников:

  • Создайте метод веб-сервиса, такой как DoSuchAndSuchProcess
  • Создайте консольное приложение, которое вызывает этот веб-метод.
  • Запланируйте консольное приложение в планировщике задач.

Используя эту методологию, вся бизнес-логика содержится в вашем веб-приложении, но у вас есть надежный диспетчер задач Windows или любой другой коммерческий диспетчер задач, чтобы запустить его и записать любую возвращаемую информацию, такую ​​как отчет об исполнении. Использование веб-службы вместо публикации на странице имеет некоторое преимущество, поскольку легче получить данные возврата из веб-службы.


10

Зачем изобретать велосипед, используйте классы Threading и Timer.

    protected void Application_Start()
    {
        Thread thread = new Thread(new ThreadStart(ThreadFunc));
        thread.IsBackground = true;
        thread.Name = "ThreadFunc";
        thread.Start();
    }

    protected void ThreadFunc()
    {
        System.Timers.Timer t = new System.Timers.Timer();
        t.Elapsed += new System.Timers.ElapsedEventHandler(TimerWorker);
        t.Interval = 10000;
        t.Enabled = true;
        t.AutoReset = true;
        t.Start();
    }

    protected void TimerWorker(object sender, System.Timers.ElapsedEventArgs e)
    {
        //work args
    }

7
Вам не нужно создавать поток, чтобы запустить таймер ...
Zyo

4
Я тоже не думаю, что это идеальное решение.
Идан Шехтер

12
@IdanShechter было бы хорошо рассказать причину, почему вы считаете это не идеальным решением
Ому

2
Поток может быть проблематичным, поскольку это не HttpRequest, некоторые данные, включающие HttpRequest, могут быть нулевыми. Например HttpRequest .ApplicationPath. Если задание написано правильно, оно будет работать. Другая проблема - перезапуск пула приложений. Если пул перезапускается слишком часто (утечки памяти ...), рабочий никогда не запустится.
Томас Кубес

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

8

Используйте планировщик Windows для запуска веб-страницы.

Чтобы запретить запуск вредоносного пользователя или паука поисковой системы, при настройке запланированного задания просто вызовите веб-страницу со строкой запроса, например: mypage.aspx? From = scheduletask

Затем при загрузке страницы просто используйте условие: if (Request.Querystring ["from"] == "scheduletask") {// executetask}

Таким образом, ни один поисковик или злоумышленник не сможет выполнить запланированное задание.


5
А еще лучше - использовать соленый алгоритм хеширования, который фактически проверяет строку запроса с немного большей безопасностью, чем волшебная фраза. Требование будет примерно таким: mypage.aspx? Salt = foo & hash = 1223523jbhdgu13t1. Вам просто нужно иметь одинаковый алгоритм хеширования как на сервере, так и на клиенте. Также добавьте жесткий лимит на сервере; сохранить, когда он был выполнен и предотвратить выполнение слишком быстро. Я могу быть параноиком, хотя.
Ненотлеп

14
Еще более безопасно использовать планировщик Windows для запуска веб-страницы, которая проверяет, поступает ли запрос с самого сервера: Request.IsLocal>> Только сам сервер может выполнять запланированные задачи, никто другой.
Заговор

У вас есть больше опыта от вашего подхода? Я собирался разработать подобный тип сервиса для нашего приложения, и теперь я не могу решить, будет ли лучше вызывать страницу с запланированным заданием или cron, или использовать систему кэширования.
JayDee


3

Кроме того, если ваше приложение использует SQL SERVER, вы можете использовать агент SQL для планирования ваших задач. Именно здесь мы обычно размещаем повторяющийся код, управляемый данными (напоминания по электронной почте, плановое обслуживание, чистки и т. Д.). Отличная функция, встроенная в агент SQL, - это параметры уведомлений об ошибках, которые могут предупредить вас в случае сбоя критической задачи.


2

Я не уверен, какие запланированные задания вы имеете в виду. Если вы имеете в виду такие вещи, как задачи «каждый час, обновите foo.xml», то используйте систему запланированных задач Windows. (Команда «at» или через контроллер.) Пусть он запустит консольное приложение или запросит специальную страницу, которая запускает процесс.

Изменить: я должен добавить, что это нормально, чтобы ваше приложение IIS работало в запланированные моменты тоже. Итак, предположим, что вы хотите проверять свою БД каждые 30 минут и отправлять пользователям по электронной почте напоминания о некоторых данных, вы можете использовать запланированные задачи для запроса этой страницы и, следовательно, получать IIS-обработку.

Если ваши потребности более сложны, вы можете рассмотреть возможность создания службы Windows и ее запуска в цикле для выполнения любой необходимой обработки. Это также имеет преимущество отделения кода для масштабирования или управления. С другой стороны, вам нужно иметь дело со службами Windows.


2

Если у вас есть сервер, вы должны использовать планировщик задач Windows. Использовать AT /? из командной строки, чтобы увидеть варианты.

В противном случае из веб-среды вам может потребоваться сделать что-то неприятное, например настроить другой компьютер для отправки запросов на определенную страницу через определенный промежуток времени.


2

Я успешно использовал Abidar в проекте ASP.NET (вот некоторая справочная информация ).

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

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


1

Вот еще один способ:

1) Создайте веб-скрипт «heartbeat», который отвечает за запуск задач, если они являются DUE или запоздалыми для запуска.

2) Создайте запланированный процесс где-нибудь (предпочтительно на том же веб-сервере), который обращается к веб-сценарию и заставляет его запускаться через регулярные промежутки времени. (например, задача расписания Windows, которая тихо запускает скрипт Heatbeat, используя IE или whathaveyou)

Тот факт, что код задачи содержится в веб-скрипте, предназначен исключительно для хранения кода в кодовой базе веб-приложения (предполагается, что оба они зависят друг от друга), что было бы проще для веб-разработчиков. ,

Альтернативный подход заключается в создании исполняемого сценария / программы сервера, который выполняет всю работу по расписанию самостоятельно и запускает сам исполняемый файл как запланированную задачу. Это может обеспечить фундаментальное разделение между веб-приложением и запланированной задачей. Следовательно, если вам нужно, чтобы запланированные задачи выполнялись даже в том случае, если веб-приложение / база данных не работает или недоступны, вам следует придерживаться этого подхода.


1
@Matias, а почему бы просто запланированному процессу не выполнять настоящую работу?
Луки,

1

Вы можете легко создать службу Windows, которая выполняет код с интервалом, используя метод ThreadPool.RegisterWaitForSingleObject. Это действительно гладко и довольно легко настроить. Этот метод является более рациональным, чем использование любого из таймеров в платформе.

Посмотрите на ссылку ниже для получения дополнительной информации:

Запуск периодического процесса в .NET с помощью службы Windows:
http://allen-conway-dotnet.blogspot.com/2009/12/running-periodic-process-in-net-using.html


0

Мы также используем консольные приложения. Если вы используете средства регистрации, такие как Log4net, вы можете правильно контролировать их выполнение. Кроме того, я не уверен, что их сложнее поддерживать, чем веб-страницы, учитывая, что вы можете делиться некоторыми из одних и тех же библиотек кода между ними, если они спроектированы правильно.

Если вы не хотите, чтобы эти задачи выполнялись по времени, у вас может быть веб-страница в административном разделе вашего сайта, которая действует как очередь. Пользователь помещает запрос на выполнение задачи, он, в свою очередь, вставляет пустую запись даты в таблицу MyProcessQueue, и ваша запланированная задача проверяет каждые X минут новую запись в MyProcessQueue. Таким образом, он запускается только тогда, когда клиент хочет, чтобы он работал.

Надеюсь, что эти предложения помогут.


0

Один из вариантов - настроить службу Windows и заставить ее вызывать запланированное задание.

В winforms я использовал таймеры, не думаю, что это будет хорошо работать в ASP.NET


-1

Новая библиотека классов планировщика заданий для .NET

Примечание. С момента создания этой библиотеки Microsoft представила новый планировщик задач (Task Scheduler 2.0) для Windows Vista. Эта библиотека является оболочкой для интерфейса Task Scheduler 1.0, который все еще доступен в Vista и совместим с Windows XP, Windows Server 2003 и Windows 2000.

http://www.codeproject.com/KB/cs/tsnewlib.aspx


Пожалуйста, удалите. Ответ дан ниже. Дубликат
Fandango68
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.