Мы имеем дело с интересной проблемой в StackOverflow.
У нас есть целая куча маленьких «дел, которые нужно сделать в ближайшее время». Примером является обновление списков «Связанные вопросы». То, что мы делали в прошлом, - это перенести эти задачи на страницы некоторых пользователей.
Это никогда не было идеальным, но это не было действительно заметно. Теперь, когда SO прошел знак вопроса в 1 000 000, эти несчастные пользователи начинают чувствовать это.
Естественное решение - отодвинуть эти задачи на задний план. Есть два широких способа сделать это, я рассматриваю.
1. В IIS как пользовательский Thread-Pool / Work-Queue
По сути, мы раскручиваем несколько (не ThreadPool , чтобы не мешать IIS) потоков и предоставляем им обслуживание некоторых коллекций, в которые мы помещаем Funcs .
Большим профессионалом здесь является простота. Нам не нужно беспокоиться о том, чтобы что-то маршалировать, и при этом мы не должны убедиться, что какой-то внешний сервис работает и реагирует.
Мы также получаем доступ ко всему нашему общему коду.
Дело в том, что мы не должны использовать фоновые потоки. Все возражения, о которых я знаю, сосредоточены вокруг голодающего IIS (если вы используете ThreadPool) и потоков, умирающих случайным образом (из-за рециркуляции AppPool).
У нас есть существующая инфраструктура, позволяющая избежать случайной смерти потока (в принципе, можно обнаружить, что задача была отменена), и ограничение количества потоков (и использование потоков, не относящихся к ThreadPool) также не представляет трудностей.
Перемещено в StackOverflow , поскольку здесь это не было адресовано.
2. Как услуга
Либо какое-нибудь стороннее решение, либо нестандартное.
По сути, мы перенаправили задачу через границу процесса в какой-нибудь сервис и просто забыли об этом. Предположительно, мы связываем некоторый код или ограничиваемся необработанным SQL + строка подключения.
Профи в том, что это «правильный путь» сделать это.
Минусы в том, что мы либо очень ограничены в своих возможностях, либо нам придется разработать какую-то систему для синхронизации этого сервиса с нашей базой кода. Нам также нужно каким-то образом подключить весь наш мониторинг и регистрацию ошибок, которые мы получаем бесплатно с опцией «In IIS».
Есть ли другие преимущества или проблемы с сервисным подходом?
Короче говоря, есть ли непредвиденные и непреодолимые проблемы, которые делают подход № 1 неработоспособным, и если да, то есть ли какие-либо хорошие сторонние сервисы, которые мы должны рассмотреть для подхода № 2?
источник
Ответы:
Несколько недель назад я задал похожий вопрос на SO. В скорлупе мой подход в течение некоторого времени заключался в разработке службы Windows. Я бы использовал NServiceBus (по сути MSMQ под прикрытием), чтобы маршалировать запросы от моего веб-приложения к моему сервису. Раньше я использовал WCF, но заставить распределенную транзакцию корректно работать над WCF всегда было проблемой в заднице. NServiceBus сделал свое дело, я мог фиксировать данные и создавать задачи в транзакции, и не беспокоиться о том, запущен ли мой сервис в данный момент. В качестве простого примера, если бы мне когда-либо нужно было отправить электронное письмо (например, электронное письмо с регистрацией), я бы создал учетную запись пользователя и включил сигнал для моей службы Windows (для отправки электронного письма) в транзакции. Обработчик сообщений на стороне службы будет принимать сообщение и обрабатывать его соответствующим образом.
С тех пор, как были выпущены ASP .NET 4.0 и AppFabric, существует целый ряд жизнеспособных альтернатив вышеуказанному механизму. Возвращаясь к вопросу, который я упомянул выше, теперь у нас есть AppInitialize AppFabric (через net.pipe), а также функция автозапуска ASP .NET 4.0, которая делает разработку Windows Services в качестве веб-приложений жизнеспособной альтернативой. Я начал делать это сейчас по ряду причин (самой большой из них является развертывание, больше не боль в заднице):
Если вы пойдете этим путем (извините за копирование и вставку из моего исходного сообщения), я бы определенно рассмотрел возможность использования фоновой логики в отдельном веб-приложении. Есть несколько причин для этого:
Это возвращает нас к аспекту маршалинга. 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 существует третий способ запуска фоновых служб, и он очень распространен в мире UNIX. Третий путь - это
CRON
работа, которая управляет частью вашей инфраструктуры. В Windows это известно какtask scheduler
и очень часто для запуска кода по расписанию. Чтобы использовать это, вы должны создать приложение командной строки, которое выполняется по заранее заданному расписанию. Преимущество этого в том, что вам не нужно беспокоиться о том, что процесс работает и работает как служба, потому что, если по какой-то причине происходит сбой, он просто запустится в следующий раз.Что касается маршалинга конкретных задач, вам действительно нужно хранить эти задачи в постоянном двоичном хранилище. Пока приложение командной строки не выберет их из хранилища и не выполнит их. Я делал это в прошлом, используя базу данных Cassandra в качестве поставщика состояния сеанса для заполнения фоновых задач для конкретных пользователей в базе данных Cassandra, а затем с помощью командной строки выбирал их и выполнял для пользователя.
Возможно, это было не типичное решение для маршалинга, но оно сработало очень хорошо для меня и оказалось очень изящным решением, потому что запланированные задачи пережили остановки, сетевые проблемы, и любая машина могла выполнить задачу, так как она была централизованной сохраняются.
Бесстыдное продвижение, но это мой проект, и решение, которое я кратко изложил, - это то, почему я создал проект: http://github.com/managedfusion/fluentcassandra/
источник
Cron + Web App
Это проверенный в бою дизайн, который масштабируется горизонтально вместе с вашей веб-фермой и гарантирует, что вы используете стек веб-технологий, который вы уже знаете.
Вот как это работает:
http://mydomain.com/system/cron
.Ура! Теперь у вас есть маршрут, который будет вызываться каждые 30 секунд. И если на обработку запроса уходит 5 минут, это никого не волнует, поскольку он не является частью запроса страницы пользователя.
cron
Действие заканчивается выглядит очень просто: у него есть список методов для выполнения на определенной частоте. Когда приходит запрос, он видит, существует ли метод, который необходимо выполнить, и вызывает соответствующий метод. Это означает, что вы можете контролировать расписание в своей базе данных , где у вас, вероятно, уже есть много других важных данных конфигурации для вашего сайта.Что еще более важно (для вас), это означает, что ваши рабочие места не должны вызываться по фиксированному графику. Вы можете написать любую логику, которую хотите определить, когда выполнять метод.
Плюсы и минусы
ProsПримечание: если есть какие-либо вопросы или проблемы, пожалуйста, добавьте комментарий . Я счастлив, чтобы уточнить.
источник
Я попробовал и использовал практически все возможные способы сделать это в моем текущем приложении. Я начал делать то же самое, что вы делаете в настоящее время, добавляя запрос пользователя для заполнения данных и затем кешируя их в дальнейшем. Я также понял, что это плохая идея (особенно если вы масштабируетесь на несколько веб-серверов, больше пользователей принимают удар).
У меня также было запланированное задание, которое встречается с 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 имеет смысл, иначе я не думаю, что это так.
источник
Я бы сделал это правильно, и у меня была бы запущена служба Windows, которая следит за «очередью». Я говорю «очередь», потому что программирование с MSMQ сродни тому, как засовывать горячие покер в ваши глазные яблоки.
Я влюбился в простоту Delayed :: Job в Rails, и что-то подобное можно легко сделать в .NET.
По сути, вы добавляете любой вид
SomethingOperation
(что-то, что имеетPerform()
метод). Затем просто сериализуйте соответствующие параметры, присвойте ему приоритет, какое-нибудь поведение повторения по умолчанию и поместите его в базу данных.Ваша служба будет просто отслеживать это и обрабатывать задания в очереди.
источник
Мы были очень довольны подходом Service Bus / Queue / Service Queue. Основная архитектура это.
Сайт отправляет сообщение в очередь
Служба Windows получает и обрабатывает сообщения в свое время
Преимущество заключается в том, что нет никаких задержек для внешней службы, к которой подключены пользователи. Служба Windows может быть отключена и обновлена без перерыва на основной сайт. Плюс это очень быстро .
Если вы не можете сохранить все свои данные в сообщении, вы всегда можете сохранить их и получить позже. Я предлагаю использовать механизм хранения документов, такой как: RavenDB или MongoDB, где очень просто хранить ваши классы без изменений.
Сайт отправляет сообщение в очередь
Служба Windows получает и обрабатывает сообщения в свое время
Для простоты мы используем: Rhino ESB и Topshelf . Конфигурация чрезвычайно проста, и ее внедрение в существующее приложение заняло очень мало времени.
источник
Мне любопытно, почему комбинация двух не является жизнеспособным вариантом. Прямо сейчас вы запускаете задания при просмотре страниц, при этом какой-то неудачный сок застревает, ожидая 10 секунд, пока страница не появится. По крайней мере, это мое понимание вашего текущего метода.
Однако эти работы выполняются все дольше и дольше по мере роста сайта, и вы не хотите нарушать работу пользователя на сайте. Даже нескольким (или, может быть, многим) незадачливым пользователям в течение дня, так что теперь вы думаете о планировании заданий в фоновом режиме.
Я не понимаю, почему фоновая работа, выполняемая через регулярные промежутки времени, не может имитировать посетителя. Сейчас я не программист Windows, но в мире Linux я бы настроил задание cron, которое выполняется через регулярные промежутки времени, и в нем было бы 2 строки кода.
Он сочетает в себе плюсы обеих систем. Это сделано в фоновом режиме. Это не влияет на пользователей. Он по-прежнему использует просмотр страницы, чтобы начать работу. Я видел этот подход раньше. Это имеет тенденцию быть средним звеном между простыми старыми путями и более сложными путями, идущими по дороге.
Обновить
Я думаю, что вы можете обойти проблему балансировки нагрузки, запустив рабочие места на самих веб-серверах. Исполнитель заданий извлекает URL из очереди заданий и запускает его так:
Из-за характера очередей заданий / сообщений задания равномерно распределяются между исполнителями заданий, что означает, что special_crafted_url в конечном итоге распределяется между вашими веб-серверами.
источник
specially_crafted_url
поступает с известного IP-адреса, вы можете добавить правило на свой балансировщик нагрузки для выполнения циклического перебора только для запросов с этого IP-адреса.Я думаю, что недостаток подхода чистого сервиса заключается в том, что у вас есть код, разбросанный по сервису и удаленный от основного приложения.
Вот что мы сделали с большими фоновыми не чувствительными ко времени заданиями, которые объединяют код и упрощают обслуживание:
Еще проще, просто сделайте вызов в консольном приложении и используйте Task Scheduler или VisualCron, чтобы превратить его в «службу».
источник
Мне понравился TopShelf. Сохраняет простоту, но все же делает это должным образом, работая в качестве службы Windows. По сути, создайте консольное приложение, добавьте около 15-20 строк кода, затем оно устанавливается как служба.
http://code.google.com/p/topshelf/
источник
Как насчет того, чтобы иметь очень простой сервис Windows, который работает на веб-сервере и периодически обращается к URL-адресу обслуживания, который выполняет ваши разные задачи. Пусть он задушит, сколько работы он выполняет в любом заданном запросе.
источник
Я собираюсь уловить очевидную тенденцию здесь и предложить перейти к модели в IIS. Я использовал это сам, и это работает очень хорошо. Реализовать приличный класс пула потоков на самом деле не так уж и сложно (с годами я расширял свой класс пула потоков для поддержки динамического создания и уничтожения потоков, повторного выполнения заданий и т. Д.). Преимущества:
По моему мнению, решение в IIS - это просто «следующий шаг» от совмещения работы с произвольным просмотром страниц.
источник
Resque это хорошо. Или даже Kthxbye, если вам нужно получить уведомление о полученном значении после его завершения.
Оба основаны на Redis / Ruby.
Честно говоря, если вы используете сервис-ориентированный подход, он действительно не нуждается в супер-интеграции с вашей текущей платформой, что я считаю плюсом. Я надеюсь, что это может быть система «забей и забудь», которая будет работать (с каким-то мониторингом) и завершать задания. Я не уверен, что его вообще нужно запускать на одной и той же платформе, поскольку он просто обновляет / изменяет информацию базы данных.
Уверен, что вы могли бы получить намного больше за гораздо меньшие деньги, если бы обрабатывали эту работу как отдельную сущность, тем более что кажется, что вы имеете дело с проблемами многопоточности. И Resque, и Kthxbye перемещают обработку в отдельные процессы, чтобы позволить ОС обрабатывать параллелизм.
Resque
Kthxbye
источник
Я бы использовал службу WCF, размещенную на WAS, слушая очередь MSMQ.
Pro,
Запустить и забыть односторонние сообщения из веб-приложения
MSMQ / WCF дросселирование и повтор
Гарантированная доставка; D
Управление Dead Letter
Распределенная обработка
WAS / MSMQ активация
Con-х
Функции MSMQ в WCF делают использование MSMQ действительно приятным. Да, вы будете кровоточить в конфигурации, но выгоды перевесят жертву.
источник
Я сталкивался с этим пару раз при разработке веб-приложений. Мы решили эту проблему, создав консольное приложение для Windows, которое выполняет задачу, и создали запланированное задание, которое запускается время от времени для фактического выполнения задачи.
источник
Вы можете шунтировать работу в фоновый поток (или много фоновых потоков), используя Rx и что-то вроде следующего:
Использовать:
Разместите все это внутри класса, в котором есть только один (он же синглтон, но делайте это правильно - используйте свой контейнер IoC для определения образа жизни).
Вы можете контролировать размер пула потоков и т. Д., Написав собственный планировщик вместо использования EventLoopScheduler (который запускает один поток).
источник
Я реализовал этот тип вещей несколько раз. В Windows я установил программу командной строки python, которая делает что-то в разное время. Эта программа также предоставляет интерфейс xmlrpc для порта. Затем задание запланированного задания выполняется каждую минуту и запрашивает интерфейсы xmlrpc. Если они не работают, он пытается их запустить. Если это не так, он пишет мне по электронной почте.
Преимущество заключается в том, что выполняемая работа не привязана к cron или расписанию. У меня есть процессное задание, которое запускается каждую секунду, но между началом нового задания я буду ждать дольше и дольше, в зависимости от того, нужно ли ему это делать. Кроме того, его можно использовать, чтобы действовать разумно, основываясь на результате. Есть ошибка 500? Есть действительно большая задержка? Сделай что-нибудь еще. Уведомить другую службу. И т.п.
И та же система работает на Unix, с небольшими изменениями.
источник
У меня нет ответа для вас, но проблема зазвонила - я помню, как некоторые случайные парни обсуждали это на подкасте однажды .
источник
Очередь задач Java API Обзор
Основные понятия задачи
В фоновой обработке App Engine задача представляет собой полное описание небольшой единицы работы. Это описание состоит из двух частей:
Задачи в качестве автономных веб-хуков
К счастью, Интернет уже предлагает такое решение в виде HTTP-запроса и его ответа. Полезная нагрузка данных - это содержимое HTTP-запроса, такого как переменные веб-формы, XML, JSON или закодированные двоичные данные. Ссылка на код - это сам URL; Фактический код - это любая логика, которую выполняет сервер при подготовке ответа.
источник
Сделать оба
Добавьте необязательный параметр к пути вопроса, который выполняет ту работу, которую вы в настоящее время выполняете в пользовательских запросах:
Обслуживание фоновых задач на большом сайте
Создайте консольное приложение, которое запускается на каждом сервере, открывает общий двоичный файл журнала IIS и считывает его в текущий конец файла. Используйте файловую систему или временной интервал для чтения вперед для сбора обновлений, когда IIS очищает журнал.
Используйте эту информацию, чтобы определить, какие страницы были просмотрены в данный момент.
Используйте URL-адреса страниц из проанализированного журнала, чтобы вызвать «лишнюю» версию URL-адреса на локальном хосте с объектом веб-клиента.
Добавьте некоторый код для переключения файлов в конце каждого периода журнала или перезапустите процесс каждый период журнала.
источник