Вопрос

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

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

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

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

1.В IIS как пользовательский пул потоков/рабочая очередь

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

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

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

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

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

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

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

2.Как услуга

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

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

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

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

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

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

Это было полезно?

Решение

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

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

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

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

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

Это возвращается к аспекту маршалирования. WCF, NServicebus/RabbitMQ/ActiveMQ и т. Д., Vanilla MSMQ, RESTFUL API (Think MVC) - все это варианты. Если вы используете Windows Workflow 4.0, вы можете разоблачить конечную точку хоста, которую может потреблять ваше веб -приложение.

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

Примечание: изначально я опубликовал еще несколько ссылок в этом сообщении, но, увы, это мой первый пост в этом обмене, и поддерживается только одна ссылка! В основном были два других, чтобы получить их Google "Смерть в Windows Services ... Long Live Appfabric!" и «Автозмушные асп-приложения». Прости за это.

Другие советы

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

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

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

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

Cron + веб -приложение

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

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

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

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

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

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

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

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

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

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

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

Я влюбился в простоту Задержка :: работа В рельсах и нечто подобное можно легко сделать в .NET.

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

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

Мы были очень довольны сервисным автобусом / очередью сообщений / подходом к обслуживанию. Основная архитектура - это это.

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

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

Service 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 });

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

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

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

Мне любопытно, почему комбинация двух не является жизнеспособным вариантом. Прямо сейчас вы запускаете задания в просмотре страниц, с некоторым несчастливым SAP, застрявшим, ожидая 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

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

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

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

  1. Создайте очередь рабочих мест (либо в памяти, либо DB, какую бы настойчивость не требуется для типов рабочих мест)
  2. Создайте веб -службу, которая выполнит задание на очередь
  3. Dead Simple Service App, которое вызывает веб -службу с указанным интервалом, оставьте все сложные вещи (поиск работы и выполнение) в веб -службу в вашей основной кодовой базе.

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

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

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

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

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

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

По моему мнению, решение INIIS-это просто «следующий шаг» от Piggyback работа на случайные просмотры страниц.

Реза это мило. Или даже Kthxbye Если вам нужно быть уведомлено о полученном значении после его завершения.

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

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

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

Реза

Kthxbye

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

Pro's

  • Пожечь и забудьте об одном способе сообщений из веб -приложения

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

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

  • Управление мертвыми письмами

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

  • Была / MSMQ активация

Мон

  • MSMQ (он еще не мертв ...

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

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

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

Принимайте все это в классе, который есть только один из (aka a Singleton, но сделайте это правильно - используйте свой контейнер IOC, чтобы определить образ жизни).

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

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

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

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

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

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

Этвуд: Да.

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

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

СПОЛСКИ: Я, так что вы поняли?

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

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

Задача концепции
В обработке фоновой обработки приложений задача - это полное описание небольшой единицы работы. Это описание состоит из двух частей:

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

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

Делать оба

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
scroll top