Как эффективно передавать нечастые сообщения между страницей ASP.NET и службой Windows? - PullRequest
2 голосов
/ 08 февраля 2012

Версия tl; dr:

Существует ли простой способ для страницы aspx отправить сообщение в службу Windows без службы, постоянно опрашивающей общий ресурс (например,таблица базы данных)?

Версия tl; but-I-read-it-anyway:

У меня есть веб-приложение ASP.NET, которое реализует оченьдлительный процесс.Я понимаю, что распространенным способом обхода проблем, связанных с перезапуском пула приложений и тайм-аутом запросов (например), является создание службы Windows для обработки длительного процесса за пределами IIS.

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

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

Приложение в основном представляет собой рассылочную почтовую рассылку (с некоторыми оговорками, которые делают его медленнее, чем обычное слияние SMTP-почты).).В среднем он используется один раз в несколько дней, и типичным случаем использования является отправка нескольких коротких почтовых заданий, а затем одного или двух длинных.Таким образом, код «отправить письмо», который я хочу переместить для службы Windows, может занять от нескольких секунд до 20 минут (и продолжает расти).

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

Я видел примеры, которые используют System.Diagnostics.Process, чтобы позволить aspxНа странице запускается консольное приложение, которое кажется ближе к тому, как на самом деле используется мое приложение (если бы я поместил почтовый код в консольное приложение), но я не думаю, что оно выходит из-под процесса IIS.

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

Дополнительные сведения: веб-приложение предназначено для платформы 3.5 и работает на старом блоке IIS 6.В своем исследовании я наткнулся на информацию о MSMQ, WCF / WAS , даже .NET Remoting , но все они чувствуют себя излишними, и мой бюджет времени на эту проблему оставляет меня достаточновремя, чтобы узнать что-то новое, но не достаточно, чтобы разобрать и сравнить все три (или потратить слишком много времени на кроличью нору).

Я просто ищу простойлегкий способ вывести некоторый код из-под процесса IIS.

Ответы [ 2 ]

3 голосов
/ 08 февраля 2012

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

Это действительно просто настроить:

  • Установить MSMQ
  • Создание частной очереди (частные очереди не реплицируются на каждой машине в вашем домене)
  • Используйте инструмент, например QueueExplorer, для просмотра сообщений или встроенный интерфейс MMC (щелкните правой кнопкой мыши мой компьютер-> управлять -> службы и приложения-> очередь сообщений)

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

// System.Messaging.Dll
// The ASP.NET sends the messages to MQ:
using (MessageQueue queue = new MessageQueue(@"computername\private$\test", QueueAccessMode.Send))
{
    using (Message message = new Message())
    {
        message.Priority = MessagePriority.Normal;
        message.Label = "A label";
        message.Body = "<content>The email message</content>";

        message.UseDeadLetterQueue = false;
        message.Recoverable = false;
        message.Formatter = new XmlMessageFormatter();

        queue.Send(message);
    }
}

// The service reads the queue in a loop:
// (more sophisticated than this)
MessageQueue queue = new MessageQueue(@"computername\private$\test", QueueAccessMode.SendAndReceive);
queue.Formatter = new XmlMessageFormatter();
Message message = queue.Receive();
string xml = (string)message.Body;
1 голос
/ 08 февраля 2012

Ну, WCF - действительно простое решение, и я использую это приложение ASP.NET для этой конкретной цели, сервер новостной рассылки - служба Windows, которая отправляет новостные рассылки. У меня не было никаких проблем с исполнением вообще. Вот хороший пример простого WCF IPC:

http://www.switchonthecode.com/tutorials/wcf-tutorial-basic-interprocess-communication

Обновление: В моем примере служба Windows является сервером, а в OnStart я делаю что-то вроде этого (пример упрощен):

protected override void OnStart(string[] args)
{
  host = new ServiceHost(typeof(NewsletterNotifier), new Uri[]{ new Uri("net.pipe://localhost") });
  host.AddServiceEndpoint(typeof(INewsletterNotifier),  new NetNamedPipeBinding(), "PipeNewsletterNotifier");
  host.Open();
}

(Не забудьте закрыть хост в сервисном событии OnStop, при паузе и продолжить вы также должны это обработать)

И затем, когда приложение ASP.NET не получает некоторые службы с сервера новостной рассылки (определяется в INewsletterNotifier):

ChannelFactory<INewsletterNotifier> pipeFactory = new ChannelFactory<INewsletterNotifier>( new NetNamedPipeBinding(), new EndpointAddress("net.pipe://localhost/PipeNewsletterNotifier"));
INewsletterNotifier pipeProxy = pipeFactory.CreateChannel();
pipeProxy.DoSomething();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...