我正在寻找一个很好的策略来真正解耦,并行处理我的Web应用程序(ASP.NET MVC/C++#)非即时进程.我将非立即数定义为不需要立即完成以呈现页面或更新信息的所有内容. 这些过程包括发送电子
这些过程包括发送电子邮件,根据数据库信息更新一些内部统计信息,从Web服务获取外部信息,这些信息只需要定期完成等等.
但是,主ASP.NET MVC应用程序和后台任务之间需要存在一些通信;例如MVC应用程序需要通知电子邮件进程发送内容.
这样做的最佳策略是什么? MSMQ?将所有这些非直接进程转换为Windows服务?我正在想象一个真正脱钩的场景,但我不想做出权衡,这会使故障排除/单元测试变得更加困难或引入大量代码.
谢谢!
.NET中的ThreadPool是基于队列的工作池,但是它由ASP.NET主机进程内部使用,因此如果您尝试更多地使用ThreadPool,则可能会降低Web Server的性能.因此,您必须创建自己的线程,将其标记为背景,并让它每隔几秒轮询一次以获得作业.
最好的方法是在数据库中创建一个Job Table,如下所示,
Table: JobQueue JobID (bigint, auto number) JobType (sendemail,calcstats) JobParams (text) IsRunning (true/false) IsOver (true/false) LastError (text)
JobThread类可能如下所示.
class JobThread{ static Thread bgThread = null; static AutoResetEvent arWait = new AutoResetEvent(false); public static void ProcessQueue(Job job) { // insert job in database job.InsertInDB(); // start queue if its not created or if its in wait if(bgThread==null){ bgThread = new Thread(new ..(WorkerProcess)); bgThread.IsBackground = true; bgThread.Start(); } else{ arWait.Set(); } } private static void WorkerProcess(object state){ while(true){ Job job = GetAvailableJob( IsProcessing = false and IsOver = flase); if(job == null){ arWait.WaitOne(10*1000);// wait ten seconds. // to increase performance // increase wait time continue; } job.IsRunning = true; job.UpdateDB(); try{ // //depending upon job type do something... } catch(Exception ex){ job.LastError = ex.ToString(); // important step // this will update your error in JobTable // for later investigation job.UpdateDB(); } job.IsRunning = false; job.IsOver = true; job.UpdateDB(); } } }
注意
对于高内存使用任务,不推荐使用此实现,ASP.NET会为大型任务提供大量内存不可用错误,例如,我们有大量的图像上传,我们需要创建缩略图并使用Bitmap对象ASP处理它们. NET只是不允许你使用更多的内存,所以我们不得不创建相同类型的Windows服务.
通过创建Windows服务,您可以创建相同的线程队列并轻松利用更多内存,并且可以在ASP.NET和Windows服务之间进行通信,您可以使用WCF或Mutex对象.
MSMQMSMQ也很棒,但它增加了配置任务,有时候很难跟踪错误.我们避免使用MSMQ,因为我们花了很多时间在我们的代码中寻找问题的答案,否则MSMQ配置就会出现问题,而错误有时候也无法提供有关问题确切位置的足够信息.在我们的自定义解决方案中,我们可以使用日志创建完整的调试版,以跟踪错这是托管程序的最大优势,在早期的Win32应用程序中,错误实际上很难追踪.