Asp.Net MVC 5 -长时间运行任务-如何确保当IIS回收AppPool时工作线程不会被丢弃

本文关键字:工作 AppPool IIS 回收 线程 确保 长时间 运行 MVC Net 任务 | 更新日期: 2023-09-27 18:18:28

我有一个数据处理MVC应用程序,它可以处理上传的文件大小从100MB到2GB,并包含几个长时间运行的操作。用户将上传文件,然后对文件中的数据进行处理,最后将对数据的一些分析发送给相关用户/客户端。

处理数据至少需要几个小时,因此为了确保用户不必一直等待,我启动了一个单独的任务来执行这个长时间运行的操作。这样,一旦文件被服务器接收并存储在磁盘上,用户将得到一个带有ReferenceID的响应,他们可以关闭浏览器。

到目前为止,它工作得很好,但在阅读了在MVC中使用"即发即弃"模式和IIS在回收过程中丢弃工作线程的问题后,我对这种方法有了一些担忧。

这个方法仍然安全吗?如果不是,我如何确保正在处理数据的线程在完成处理并将数据发送给客户端之前不会死亡?(以相对简单的方式)

该应用程序运行在。net 4.5上,所以我认为我现在不能使用HostingEnvironment.QueueBackgroundWorkItem

在控制器上使用Async/Await有帮助吗?

我还考虑过在应用服务器上使用消息队列来存储消息,一旦文件存储到磁盘,然后使DataProcessor成为一个单独的服务/进程,然后侦听队列。如果队列是可恢复的,那么它将向我保证,即使服务器崩溃或线程在完成处理数据之前被丢弃,消息最终也将得到处理。这是一个更好的方法吗?

我的当前设置在

下面控制器

public ActionResult ProcessFiles() 
{    
    HttpFileCollectionBase uploadedfiles = Request.Files;    
    var isValid = ValidateService.ValidateFiles(uploadedFiles);
    if(!isValid){
        return View("Error");
    }
    var referenceId = DataProcessor.ProcessData(uploadedFiles);
    return View(referenceId);    
}
业务逻辑

public Class DataProcessor 
   {    
     public int ProcessFiles(HttpFileCollectionBase uploadedFiles) 
     {    
      var referenceId = GetUniqueReferenceIdForCurrentSession();
      var location = SaveIncomingFilesToDisk(referenceId, uploadedFiles);
      //ProcessData makes a DB call and takes a few hours to complete. 
      TaskFactory.StartNew(() => ProcessData(ReferenceId,location))
                 .ContinueWith((prevTask) => 
      {
         Log.Info("Completed Processing. Carrying on with other work");
         //Below method takes about 30 mins to an hour
         SendDataToRelatedClients(ReferenceId);  
      }    
      return referenceId;
     }
   }

引用

http://blog.stephencleary.com/2014/06/fire-and-forget-on-asp-net.html

Apppool回收和Asp.net线程?

Asp.Net MVC 5 -长时间运行任务-如何确保当IIS回收AppPool时工作线程不会被丢弃

这个方法仍然安全吗?

从来都不安全。

在控制器上使用Async/Await有帮助吗?

该应用程序运行在。net 4.5上,所以不要认为我将能够使用HostingEnvironment。QueueBackgroundWorkItem .

我有一个AspNetBackgroundTasks库,基本上做同样的事情作为QueueBackgroundWorkItem(有微小的差异)。然而…

我还考虑过在应用服务器上使用消息队列来存储消息,一旦文件存储到磁盘,然后使DataProcessor成为一个单独的服务/进程,然后侦听队列。如果队列是可恢复的,那么它将向我保证,即使服务器崩溃或线程在完成处理数据之前被丢弃,消息最终也将得到处理。这是一个更好的方法吗?

是的。这是唯一可靠的方法。这就是我在博客文章中所说的"合适的分布式架构"。

不,不安全。在服务器上创建一个服务应用程序来处理这些请求并发布结果。如果你托管在Azure上,利用他们的WebJob服务。