如何有效地在ASP.NET页面和Windows服务之间传递不频繁的消息?

时间:2012-02-08 19:46:09

标签: asp.net windows-services

tl; dr版本:

是否有一种简单的方法可以让aspx页面将消息推送到Windows服务w / out服务不断轮询共享资源(例如数据库表)?

tl; but-I-read-it-anyway version:

我有一个ASP.NET Web应用程序,它实现了一个非常长的运行过程。据我所知,由于应用程序池回收和请求超时(例如)的常见问题是创建Windows服务来处理IIS之外的长时间运行过程。

我很熟悉ASP.NET,之前我已经构建了简单的Windows服务,但我可以使用一些建议来了解如何在网页和Windows服务之间传递消息。

显而易见的简单解决方案是使用共享数据库 - 网页将请求写入“作业”表,服务监视该表以了解何时处理作业。但是,我不确定这是否适合我的应用程序使用方式。

该应用程序基本上是一个跳跃的电子邮件新闻邮件邮件(有一些警告,使其比典型的SMTP邮件合并慢)。它平均每隔几天使用一次,典型的用例是发送几个简短的电子邮件作业,然后发送一个或两个长作业。因此,“发送电子邮件”代码,即我想要移动Windows服务的代码,可能需要几秒到20分钟(并且还在增长)才能执行。

因此,似乎对于Web应用程序在规模的短端响应,服务必须每隔几秒轮询一次数据库,这样用户就不会等待更长时间才能启动作业采取执行。但是,在没有使用该应用程序的时候,这似乎对数据库造成了很多无用的负担。

我见过使用System.Diagnostics.Process让aspx页面运行控制台应用程序的示例,这看起来更接近我的应用程序的实际使用方式(如果我将邮件代码放在控制台应用程序中),但我不认为从IIS过程中得到它。

所以我的问题可归结为:网页是否有一种简单的方法可以将窗口服务推送到(或以其他方式引起反应)Windows服务不断轮询共享资源(例如数据库表) )?或者,这个常量数据库轮询是否比我想象的要少?

更多详细信息:该网络应用程序面向3.5框架,并在旧的死水IIS 6框上运行。在我的研究中,我在MSMQ,WCF/WAS,甚至是.NET Remoting上都遇到过这些信息,但他们都觉得有点矫枉过正,而且这个问题的时间预算让我有足够的时间学习某事< / em> new,但还不足以解析和比较所有三个(或者花费太多时间在google rabbit hole上)。

我真的只是在寻找一种简单的轻量级方法来从IIS进程中移出一些代码。

2 个答案:

答案 0 :(得分:3)

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 :(得分:1)

嗯,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应用程序不是来自Newsletter服务器的某些服务(在INewsletterNotifier中定义)时:

ChannelFactory<INewsletterNotifier> pipeFactory = new ChannelFactory<INewsletterNotifier>( new NetNamedPipeBinding(), new EndpointAddress("net.pipe://localhost/PipeNewsletterNotifier"));
INewsletterNotifier pipeProxy = pipeFactory.CreateChannel();
pipeProxy.DoSomething();