Обслуживание фоновых задач на большом сайте

49

Мы имеем дело с интересной проблемой в StackOverflow.

У нас есть целая куча маленьких «дел, которые нужно сделать в ближайшее время». Примером является обновление списков «Связанные вопросы». То, что мы делали в прошлом, - это перенести эти задачи на страницы некоторых пользователей.

Это никогда не было идеальным, но это не было действительно заметно. Теперь, когда SO прошел знак вопроса в 1 000 000, эти несчастные пользователи начинают чувствовать это.

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

1. В IIS как пользовательский Thread-Pool / Work-Queue

По сути, мы раскручиваем несколько (не ThreadPool , чтобы не мешать IIS) потоков и предоставляем им обслуживание некоторых коллекций, в которые мы помещаем Funcs .

Большим профессионалом здесь является простота. Нам не нужно беспокоиться о том, чтобы что-то маршалировать, и при этом мы не должны убедиться, что какой-то внешний сервис работает и реагирует.

Мы также получаем доступ ко всему нашему общему коду.

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

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

Я пропускаю какие-либо другие возражения против пула потоков / рабочих процессов IIS?

Перемещено в StackOverflow , поскольку здесь это не было адресовано.

2. Как услуга

Либо какое-нибудь стороннее решение, либо нестандартное.

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

Профи в том, что это «правильный путь» сделать это.

Минусы в том, что мы либо очень ограничены в своих возможностях, либо нам придется разработать какую-то систему для синхронизации этого сервиса с нашей базой кода. Нам также нужно каким-то образом подключить весь наш мониторинг и регистрацию ошибок, которые мы получаем бесплатно с опцией «In IIS».

Есть ли другие преимущества или проблемы с сервисным подходом?

Короче говоря, есть ли непредвиденные и непреодолимые проблемы, которые делают подход № 1 неработоспособным, и если да, то есть ли какие-либо хорошие сторонние сервисы, которые мы должны рассмотреть для подхода № 2?

Кевин Монтроз
источник
Правильный путь - это то, что когда вы решаете пойти другим путем, вы оглядываетесь назад и говорите, что мы должны были поступить правильно. Выбирай с умом. Я не достаточно знаком с миром IIS, чтобы прокомментировать эту конкретную проблему.
Крис
2
Мне любопытно, потому что у меня есть похожий сценарий (в гораздо меньших масштабах), и я тоже просто поддерживаю некоторых случайных пользователей незадачливым соединением. Я не знаком с лучшим решением, поэтому я буду следовать здесь. :-)
pc1oad1etter
7
Я не понимаю, почему это не на StackOverflow. Это инженерный компромисс, а не субъективная оценка. Вы просите анализ различных подходов - это все объективно. Только когда анализ прояснил, в чем именно заключаются компромиссы, возникает ли в этом какая-либо субъективность, и, насколько я понимаю, ваш вопрос не в том, «что я должен найти более важным, мои ресурсы времени и сервера или время моего пользователя? ' или что-то подобное.
Джорен
@Kevin Montrose - из ваших комментариев кажется, что вы проводите различие между «нужно сделать как можно скорее» и «запланировано на определенный промежуток времени». Можете ли вы объяснить, почему это два разных типа фоновых задач, которые требуют другого шаблона / инфраструктуры?
Портман
@Portman - Принципиальное отличие состоит в том, что задачи «скоро» не могут быть спекулятивными, нам действительно нужно подождать, пока мы не узнаем, что они должны быть выполнены. Некоторые подсчеты конвертов показывают, что если бы мы переместили запросы «Связанные вопросы» (только один из многих) на «тупую» вкладку cron, это заняло бы ок. неделя солидного исполнения для проработки всех вопросов. Как правило, мы также хотели бы, чтобы они запускались как можно быстрее (без влияния на взаимодействие с пользователем), тогда как наши интервальные задачи могут выполняться не чаще, чем раз в 5 минут (и, как правило, гораздо реже).
Кевин Монтроз

Ответы:

17

Несколько недель назад я задал похожий вопрос на SO. В скорлупе мой подход в течение некоторого времени заключался в разработке службы Windows. Я бы использовал NServiceBus (по сути MSMQ под прикрытием), чтобы маршалировать запросы от моего веб-приложения к моему сервису. Раньше я использовал WCF, но заставить распределенную транзакцию корректно работать над WCF всегда было проблемой в заднице. NServiceBus сделал свое дело, я мог фиксировать данные и создавать задачи в транзакции, и не беспокоиться о том, запущен ли мой сервис в данный момент. В качестве простого примера, если бы мне когда-либо нужно было отправить электронное письмо (например, электронное письмо с регистрацией), я бы создал учетную запись пользователя и включил сигнал для моей службы Windows (для отправки электронного письма) в транзакции. Обработчик сообщений на стороне службы будет принимать сообщение и обрабатывать его соответствующим образом.

С тех пор, как были выпущены ASP .NET 4.0 и AppFabric, существует целый ряд жизнеспособных альтернатив вышеуказанному механизму. Возвращаясь к вопросу, который я упомянул выше, теперь у нас есть AppInitialize AppFabric (через net.pipe), а также функция автозапуска ASP .NET 4.0, которая делает разработку Windows Services в качестве веб-приложений жизнеспособной альтернативой. Я начал делать это сейчас по ряду причин (самой большой из них является развертывание, больше не боль в заднице):

  1. Вы можете разработать веб-интерфейс поверх своего сервиса (поскольку он работает как веб-приложение). Это очень полезно, чтобы увидеть, что происходит во время выполнения.
  2. Ваша модель развертывания для ваших веб-приложений будет работать для вашего приложения-службы.
  3. IIS предоставляет несколько удобных функций для обработки сбоев приложений (в некоторых отношениях сходных со службой Windows).
  4. Веб-разработчики очень хорошо знакомы с разработкой веб-приложений (естественно), большинство из них мало знают о наилучшей практике при разработке службы Windows.
  5. Он предоставляет ряд альтернатив для предоставления API для использования другими приложениями.

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

  1. Безопасность . Может быть другая модель безопасности для интерфейса пользователя, отображающего информацию о запущенных фоновых процессах. Я бы не хотел показывать этот интерфейс кому-либо еще, кроме команды ops. Кроме того, веб-приложение может работать от имени другого пользователя с повышенными правами доступа.
  2. Техническое обслуживание . Было бы замечательно иметь возможность развертывать изменения в приложении, в котором размещены фоновые процессы, не влияя на использование пользователем интерфейсного веб-сайта.
  3. Производительность . Отделение приложения от основного пользовательского сайта, обрабатывающего пользовательские запросы, означает, что фоновые потоки не уменьшат способность IIS обрабатывать очередь входящих запросов. Кроме того, приложение, обрабатывающее фоновые задачи, может быть развернуто на отдельном сервере, если требуется.

Это возвращает нас к аспекту маршалинга. WCF, NServiceBus / RabbitMQ / ActiveMQ и т. Д., Ванильный MSMQ, RESTful API (например, MVC) - все это варианты. Если вы используете Windows Workflow 4.0, вы можете предоставить конечную точку хоста, которую может использовать ваше веб-приложение.

Подход веб-хостинга для сервисов все еще довольно новый для меня, только время покажет, был ли это правильный выбор. Пока все хорошо, хотя. Кстати, если вы не хотите использовать AppFabric (я не смог, потому что по какой-то странной причине Windows Server Web Edition не поддерживается), возможность автозапуска, упомянутая в посте Гу, работает хорошо. Держитесь подальше от файла applicationhost.config, хотя все, что в этом посте, можно настроить через консоль IIS (редактор конфигурации на уровне главного сервера).

Примечание: я первоначально разместил еще несколько ссылок в этом сообщении, но, увы, это мой первый пост в этом обмене, и поддерживается только одна ссылка! Было в основном два других, чтобы получить их Google "Смерть службам Windows ... Long Live AppFabric!" и "автозапуск-asp-net-приложения". Прости за это.

Роланда
источник
Основная идея использования отдельного веб-сайта в качестве службы является интригующей, которую я не рассматривал ...
Кевин Монтроуз
Роланд, возможно, я что-то здесь упускаю, но вы, похоже, говорите, что взаимодействовали со службой Windows из своего обработчика NServiceBus, после чего служба отправляет электронное письмо. Если я прав, могу ли я спросить, почему вы просто не отправляете письмо от обработчика сообщений NServiceBus, которое было бы очень легко разрабатывать, тестировать и развертывать?
Шон Кирон
Веб-сайт отправляет сообщение в службу Windows. Обработчик сообщений службы Windows NServiceBus забирает сообщение и отправляет сообщение. По сути, это то же самое, что процесс, который вы описываете.
Роланд
22

На самом деле в Windows существует третий способ запуска фоновых служб, и он очень распространен в мире UNIX. Третий путь - это CRONработа, которая управляет частью вашей инфраструктуры. В Windows это известно как task schedulerи очень часто для запуска кода по расписанию. Чтобы использовать это, вы должны создать приложение командной строки, которое выполняется по заранее заданному расписанию. Преимущество этого в том, что вам не нужно беспокоиться о том, что процесс работает и работает как служба, потому что, если по какой-то причине происходит сбой, он просто запустится в следующий раз.

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

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

Бесстыдное продвижение, но это мой проект, и решение, которое я кратко изложил, - это то, почему я создал проект: http://github.com/managedfusion/fluentcassandra/

Ник Берарди
источник
2
Я делаю это с помощью службы общего хостинга, поскольку у меня нет доступа к оболочке. Напишите страницу PHP, которая делает что-то важное, а затем задайте задачу cron, которая периодически загружает страницу, используя wget или lynx. Это звучит как то, что в этом случае будет работать и будет чрезвычайно простым, вряд ли требующим изменения в том, как все в настоящее время делается.
Ricket
Какое простое решение. Это породило идеи для моего собственного проекта, которые я еще даже не рассматривал. Кроме того, у вас есть полный доступ к существующей кодовой базе. Просто добавьте консольный проект в решение и укажите ссылки на существующие проекты.
Тим Мерфи
10

Cron + Web App

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

Вот как это работает:

  1. Создайте контроллер / действие в вашем веб-приложении для обработки запланированных фоновых задач. По договоренности я обычно называю свою http://mydomain.com/system/cron.
  2. В целях безопасности это действие должно быть заблокировано только для аутентифицированных IP-адресов в локальной сети.
  3. На отдельном компьютере установите Wget и настройте запланированное задание, чтобы wget извлекал ресурс из шага 1. Вы можете запускать задание так часто, как хотите (я обычно выбираю 30 секунд). Не забудьте передать соответствующий аргумент cookie в Wget, чтобы он аутентифицировался в вашем веб-приложении.
  4. Для обеспечения избыточности вы также можете установить второй запланированный wget на второй компьютер.

Ура! Теперь у вас есть маршрут, который будет вызываться каждые 30 секунд. И если на обработку запроса уходит 5 минут, это никого не волнует, поскольку он не является частью запроса страницы пользователя.

cronДействие заканчивается выглядит очень просто: у него есть список методов для выполнения на определенной частоте. Когда приходит запрос, он видит, существует ли метод, который необходимо выполнить, и вызывает соответствующий метод. Это означает, что вы можете контролировать расписание в своей базе данных , где у вас, вероятно, уже есть много других важных данных конфигурации для вашего сайта.

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

Плюсы и минусы

Pros
  • Вы уже очень хорошо пишете код ASP.NET MVC, так что это позволяет вам писать фоновые задачи на той же платформе, на которой вы пишете остальную часть своего решения.
  • Задачи выполняются в том же контексте, что и ваше веб-приложение, поэтому вы можете совместно использовать кеш и использовать уже существующие вспомогательные методы .
  • Если у вас есть wget для получения URI с балансировкой нагрузки , то ваши фоновые задачи теперь также с балансировкой нагрузки.
  • Одновременное развертывание - вам не нужно беспокоиться о синхронизации вашего веб-приложения с логикой фоновой задачи, потому что все они находятся в одном развертывании.
Cons
  • За прошедшие годы несколько человек сказали мне, что этот дизайн «сильно связан», но при нажатии они не смогли сформулировать, почему это плохо.

Примечание: если есть какие-либо вопросы или проблемы, пожалуйста, добавьте комментарий . Я счастлив, чтобы уточнить.

Портман
источник
7

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

У меня также было запланированное задание, которое встречается с URL-адресом в приложении ASP.NET - это достойное решение, но оно начинает ломаться с той минуты, когда вы масштабируете один веб-сервер.

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

Во-вторых, я написал библиотеку для упаковки Quartz.NET под названием DaemonMaster - она ​​позволяет легко помещать DLL в каталог и запускать ее в службе Windows. Я обнаружил, что это помогает избежать некоторых раздражающих частей работы со службой Windows, а также очищает API Quartz.NET. Сервисы, которые работают через DaemonMaster, имеют два разных варианта, первый - это задания, которые нужно запускать каждую ночь или каждые X минут. Другие задания работают вне очереди на основе данных, поступающих из приложения ASP.NET. Приложение ASP.NET удаляет объекты JSON в RabbitMQ, а сервисный опрос RabbitMQ затем обрабатывает данные.

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

Джеймс Эйвери
источник
6

Я бы сделал это правильно, и у меня была бы запущена служба Windows, которая следит за «очередью». Я говорю «очередь», потому что программирование с MSMQ сродни тому, как засовывать горячие покер в ваши глазные яблоки.

Я влюбился в простоту Delayed :: Job в Rails, и что-то подобное можно легко сделать в .NET.

По сути, вы добавляете любой вид SomethingOperation(что-то, что имеет Perform()метод). Затем просто сериализуйте соответствующие параметры, присвойте ему приоритет, какое-нибудь поведение повторения по умолчанию и поместите его в базу данных.

Ваша служба будет просто отслеживать это и обрабатывать задания в очереди.

Бен Шейрман
источник
Сериализация соответствующих параметров на самом деле не «просто», а почти «все». Это одно из моих больших замечаний по поводу отдельного подхода к процессу ...
Кевин Монтроуз
Да, это то же самое решение, которое я использовал, однако я сериализовал весь объект в базу данных как двоичный файл, а затем вытащил их для выполнения. Я использовал Cassandra в качестве своего постоянного хранилища и Task Scheduler в качестве своего CRON-планировщика для приложения командной строки, которое будет запускать и выполнять задачи.
Ник Берарди
Мы начали с того, что включили в сообщение простой фрагмент данных и в итоге бросили весь объект. Это все еще отлично сработало. Я хотел бы рассмотреть разделение, поскольку оно имеет и другие преимущества.
Натан Палмер
@Kevin - если бы у нас были люди с большим количеством сериализационных историй ....
Марк Гравелл
4

Мы были очень довольны подходом Service Bus / Queue / Service Queue. Основная архитектура это.

Сайт отправляет сообщение в очередь

bus.Send(new ProjectApproved()); // returns immediately

Служба Windows получает и обрабатывает сообщения в свое время

public class DoesSomethingAwesome : ConsumerOf<ProjectApproved>
{
   public void Consume(ProjectApproved Message)
   {
      // Do something "offline"
   }
}

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

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

Сайт отправляет сообщение в очередь

// Save your object
store.Save(completeProject);

// Send a message indicating its ready to be processed
bus.Send(new ProjectApproved() { ProjectId = completeProject.Id });

Служба Windows получает и обрабатывает сообщения в свое время

public class DoesSomethingAwesome : ConsumerOf<ProjectApproved>
{
   public void Consume(ProjectApproved Message)
   {
      // Retrieve your object back
      var completeProject = store.Get(Message.ProjectId);
   }
}

Для простоты мы используем: Rhino ESB и Topshelf . Конфигурация чрезвычайно проста, и ее внедрение в существующее приложение заняло очень мало времени.

Натан Палмер
источник
В любом случае, использование служебной шины с CQRS - это всегда хороший способ улучшить вашу масштабируемость
thinkbeforecoding 22.10.10
3

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

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

Я не понимаю, почему фоновая работа, выполняемая через регулярные промежутки времени, не может имитировать посетителя. Сейчас я не программист Windows, но в мире Linux я бы настроил задание cron, которое выполняется через регулярные промежутки времени, и в нем было бы 2 строки кода.

#!/bin/bash
wget -O /dev/null http://stackoverflow.com/specially_crafted_url

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

Обновить

Я думаю, что вы можете обойти проблему балансировки нагрузки, запустив рабочие места на самих веб-серверах. Исполнитель заданий извлекает URL из очереди заданий и запускает его так:

wget -O /dev/null http://localhost/specially_crafted_url

Из-за характера очередей заданий / сообщений задания равномерно распределяются между исполнителями заданий, что означает, что special_crafted_url в конечном итоге распределяется между вашими веб-серверами.

mellowsoon
источник
Мы уже делаем это для всего, что выполняется с предсказуемыми интервалами, и у нас остаются вещи, которые нельзя предсказать слишком далеко заранее. Например, «блок связанных вопросов» обновляется только для тех вопросов, которые были просмотрены недавно. Списки вопросов с тегами также кэшируются, только если кто-то захочет проверить эти теги. Поскольку у нас более миллиона вопросов и мы приближаемся к тегам 25 тысяч, мы не можем выполнить все связанные задачи (и это только 2 примера) «на всякий случай».
Кевин Монтроз
Есть также проблемы с балансировкой нагрузки, так как SO распределен по нескольким серверам. По сути, если вы зайдете на stackoverflow.com, вы всегда попадете на один и тот же сервер. Подход wget заставил бы нас перенести все задачи на один сервер (или реально переработать нашу настройку балансировки нагрузки), что было бы очень болезненно.
Кевин Монтроуз
Было бы хорошо, если бы все происходило регулярно, а? Я понимаю, что вы говорите, но методология, изложенная выше (и я думаю, упомянутая несколькими другими людьми) не меняется. Когда при просмотре страницы появляется сообщение «пора запускать это задание», вы помещаете задание в очередь сообщений. Длительное фоновое задание запускает найденные задания. В этом случае задания являются не чем иным, как URL-адресами, которые необходимо запрашивать. Хе-хе Вы, вероятно, можете установить это на общем сервере за 20 долларов в месяц, так как для его работы не требуется ваша кодовая база. Посмотрите на Amazon SQS для удобной службы обмена сообщениями.
mellowsoon
По вопросам баланса нагрузки. Где есть воля, там есть способ! Вместо того, чтобы отправлять запрос на stackoverflow.com, вы можете случайно подключиться к серверу, используя его IP-адрес. Если балансировщик нагрузки проверяет файлы cookie для отправки запросов, вы можете подделать файлы cookie. Если он проверяет IP-адрес, вы, возможно, даже подделаете его (поскольку вам не важен ответ от сервера).
mellowsoon
Договорились, что распределение нагрузки не должно быть причиной, чтобы этого не делать. Поскольку запрос specially_crafted_urlпоступает с известного IP-адреса, вы можете добавить правило на свой балансировщик нагрузки для выполнения циклического перебора только для запросов с этого IP-адреса.
Портман
2

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

Вот что мы сделали с большими фоновыми не чувствительными ко времени заданиями, которые объединяют код и упрощают обслуживание:

  1. Создайте очередь заданий (либо в памяти, либо в БД, независимо от того, какое сохранение требуется для типов заданий)
  2. Создать веб-сервис, который будет выполнять поставленные в очередь задания
  3. Мертвое простое приложение-служба, которое вызывает веб-службу с заданным интервалом, оставляя все сложные вещи (поиск и выполнение заданий) веб-службе в вашей основной базе кода.

Еще проще, просто сделайте вызов в консольном приложении и используйте Task Scheduler или VisualCron, чтобы превратить его в «службу».

Brandon
источник
1
Я получил именно это в большом приложении на работе - службе Windows, которая периодически запускает веб-приложение. Веб-приложение остается без сохранения состояния, вытягивая состояние из базы данных по мере необходимости. Работает угощение.
Беван
1

Мне понравился TopShelf. Сохраняет простоту, но все же делает это должным образом, работая в качестве службы Windows. По сути, создайте консольное приложение, добавьте около 15-20 строк кода, затем оно устанавливается как служба.

http://code.google.com/p/topshelf/

Шейн
источник
1

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

Роб Соберс
источник
1

Я собираюсь уловить очевидную тенденцию здесь и предложить перейти к модели в IIS. Я использовал это сам, и это работает очень хорошо. Реализовать приличный класс пула потоков на самом деле не так уж и сложно (с годами я расширял свой класс пула потоков для поддержки динамического создания и уничтожения потоков, повторного выполнения заданий и т. Д.). Преимущества:

  • Нет внешнего сервиса для мониторинга
  • Простота реализации: нет межпроцессного сортировки, нет расширенного мониторинга заданий
  • Вы все еще находитесь в процессе IIS, так что вы можете вести все свои обычные записи и т. Д. (Нет необходимости в нескольких файлах журнала)
  • Значительно упрощенное развертывание (когда вы обновляете сервис, вы должны остановить сервис, скопировать файлы, запустить сервис - это в дополнение к вашим обычным обновлениям кода сайта)

По моему мнению, решение в IIS - это просто «следующий шаг» от совмещения работы с произвольным просмотром страниц.

Дин Хардинг
источник
1

Resque это хорошо. Или даже Kthxbye, если вам нужно получить уведомление о полученном значении после его завершения.

Оба основаны на Redis / Ruby.

Честно говоря, если вы используете сервис-ориентированный подход, он действительно не нуждается в супер-интеграции с вашей текущей платформой, что я считаю плюсом. Я надеюсь, что это может быть система «забей и забудь», которая будет работать (с каким-то мониторингом) и завершать задания. Я не уверен, что его вообще нужно запускать на одной и той же платформе, поскольку он просто обновляет / изменяет информацию базы данных.

Уверен, что вы могли бы получить намного больше за гораздо меньшие деньги, если бы обрабатывали эту работу как отдельную сущность, тем более что кажется, что вы имеете дело с проблемами многопоточности. И Resque, и Kthxbye перемещают обработку в отдельные процессы, чтобы позволить ОС обрабатывать параллелизм.

Resque

Kthxbye

Lukas
источник
Я должен попробовать Kthxbye хотя бы из-за великого имени!
Натан Палмер
в значительной степени потрясающий. дальше будет ОРЛЫ? библиотека. вероятно, для какого-то мониторинга статистики ...;)
Lukas
0

Я бы использовал службу WCF, размещенную на WAS, слушая очередь MSMQ.

Pro,

  • Запустить и забыть односторонние сообщения из веб-приложения

  • MSMQ / WCF дросселирование и повтор

  • Гарантированная доставка; D

  • Управление Dead Letter

  • Распределенная обработка

  • WAS / MSMQ активация

Con-х

  • MSMQ (он еще не умер ... пока)

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


источник
0

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

Джон Кристенсен
источник
0

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

var scheduler = new EventLoopScheduler( SchedulerThreadName );
_workToDo = new Subject<Action>();
var queueSubscription = _workToDo.ObserveOn( scheduler ).Subscribe( work => work() );
_cleanup = new CompositeDisposable( queueSubscription, scheduler );

Использовать:

var work = () => { ... };
_workToDo.OnNext( work ); // Can also put on error / on complete in here

Разместите все это внутри класса, в котором есть только один (он же синглтон, но делайте это правильно - используйте свой контейнер IoC для определения образа жизни).

Вы можете контролировать размер пула потоков и т. Д., Написав собственный планировщик вместо использования EventLoopScheduler (который запускает один поток).

Нил
источник
0

Я реализовал этот тип вещей несколько раз. В Windows я установил программу командной строки python, которая делает что-то в разное время. Эта программа также предоставляет интерфейс xmlrpc для порта. Затем задание запланированного задания выполняется каждую минуту и ​​запрашивает интерфейсы xmlrpc. Если они не работают, он пытается их запустить. Если это не так, он пишет мне по электронной почте.

Преимущество заключается в том, что выполняемая работа не привязана к cron или расписанию. У меня есть процессное задание, которое запускается каждую секунду, но между началом нового задания я буду ждать дольше и дольше, в зависимости от того, нужно ли ему это делать. Кроме того, его можно использовать, чтобы действовать разумно, основываясь на результате. Есть ошибка 500? Есть действительно большая задержка? Сделай что-нибудь еще. Уведомить другую службу. И т.п.

И та же система работает на Unix, с небольшими изменениями.

Кристофер Махан
источник
0

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

Spolsky: Я заметил, что один из вопросов, которые вы задали в блоге, был о том, как вы должны справляться с текущими задачами по обслуживанию в целом?

Этвуд: Да.

Спольский: Это справедливая характеристика? У каждого веб-сайта есть некоторые задачи, которые вы не хотите выполнять во время загрузки веб-страницы, но вы хотите выполнять их с некоторым повторением.

Этвуд: Да, фоновые задачи вроде вещей.

Spolsky: Да, так что вы выяснили?

Этвуд: Ну, я изначально спросил в Твиттере, потому что я просто хотел что-то более легкое. Я действительно не хотел писать сервис Windows. Я чувствовал, что это было вне группового кода. Плюс код, который фактически выполняет эту работу, на самом деле является веб-страницей, потому что для меня это логическая единица работы на веб-сайте - это веб-страница. Итак, это действительно так, как будто мы перезваниваем на веб-сайт, это как очередной запрос на веб-сайте, так что я рассматривал его как нечто, что должно оставаться встроенным, и тот небольшой подход, который мы предложили, который был рекомендован мне в Twitter По сути, нужно было что-то добавить в кеш приложения с фиксированным сроком действия, затем у вас есть обратный вызов, поэтому, когда он истекает, он вызывает определенную функцию, которая выполняет свою работу, а затем вы добавляете это обратно в кеш с тем же сроком действия.

Oddthinking
источник
1
Да, это работает для сайтов, намного меньших, чем StackOverflow. К сожалению, масштаб является большой проблемой (или, к счастью, в зависимости от того, как вы на это смотрите).
Кевин Монтроз
@Kevin Montrose, я прошу полное невежество домена здесь. Не могли бы вы объяснить, почему секретная веб-страница (ы) выполняет работу (возможно, небольшими единицами) и вызывается обновлением задания страницы / cron где-то еще, не масштабируется? Я не сомневаюсь, что вы правы, но я хотел бы учиться.
Нечетное
Ваше конкретное предложение (срок действия кэша истекает) не масштабируется, потому что все окончания срока действия кэша (в ASP.NET) выполняются одним потоком (это умный взлом для небольших сайтов, как раньше было SO). Задача cron не масштабируется, потому что мы переросли один сервер (SO сейчас 3 и продолжает расти), и любая задача cron будет попадать на один сервер (по крайней мере, изменение этого инварианта будет очень болезненным с нашей нагрузкой). настройка баланса). Задача cron также должна выполняться очень часто, так как эти задачи повторяются в течение нескольких минут.
Кевин Монтроуз
Стоит отметить, что мы используем планирование «cron style» для менее частого выполнения, с фиксированным интервалом, задачами, такими как выдача пропусков и ежедневные уведомления по электронной почте.
Кевин Монтроз
0

Очередь задач Java API Обзор

Основные понятия задачи
В фоновой обработке App Engine задача представляет собой полное описание небольшой единицы работы. Это описание состоит из двух частей:

  • Полезная нагрузка данных, которая параметризует задачу.
  • Код, который реализует задачу.

Задачи в качестве автономных веб-хуков
К счастью, Интернет уже предлагает такое решение в виде HTTP-запроса и его ответа. Полезная нагрузка данных - это содержимое HTTP-запроса, такого как переменные веб-формы, XML, JSON или закодированные двоичные данные. Ссылка на код - это сам URL; Фактический код - это любая логика, которую выполняет сервер при подготовке ответа.

antony.trupe
источник
Я не предлагаю использовать API очереди задач GAE, но следую их модели. Некоторое время они продумали это и написали реализацию.
antony.trupe 22.10.10
0

Сделать оба

Добавьте необязательный параметр к пути вопроса, который выполняет ту работу, которую вы в настоящее время выполняете в пользовательских запросах:

Обслуживание фоновых задач на большом сайте

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

Используйте эту информацию, чтобы определить, какие страницы были просмотрены в данный момент.

Используйте URL-адреса страниц из проанализированного журнала, чтобы вызвать «лишнюю» версию URL-адреса на локальном хосте с объектом веб-клиента.

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

Билл
источник