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进程中移出一些代码。
答案 0 :(得分:3)
MSMQ怎么样?您可以获得要通过电子邮件可靠传递的消息,并且服务器会以您喜欢的频率从队列中读取。
设置非常简单:
以下是一些非常快速的未经测试的代码作为示例。如果需要,您可以为消息创建自己的格式化程序,如果消息需要冗余,则使用事务。
// 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();