如何在ASP.NET Web API中对后台任务进行排队

本文关键字:后台任务 排队 API ASP NET Web | 更新日期: 2023-09-27 17:57:39

我有一个webapi,旨在以队列方式处理报告。应用程序采取的步骤如下:

  • 接收内容
  • 将内容映射到对象并将其放入队列
  • 轮询队列中的挂起项目
  • 一次处理一个队列中的项目

我想使用实体框架来创建一个排队项目的数据库,例如:

public class EFBatchItem
{
    [Key]
    public string BatchId { get; set; }
    public DateTime DateCreated { get; set; }
    public DateTime DateCompleted { get; set; }
    public string BatchItem { get; set; }
    public BatchStatus Status { get; set; }
}

我的问题是,使用NServiceBus、BlockingCollection或ConcurrentQeueue,有没有比不断轮询数据库并逐个取出挂起的项目更有效的方法?我以前从未使用过队列。

一种想法是创建一个任务队列,并在一个单独的线程上处理所有挂起的任务。有点类似于用线程处理队列的最有效方法,但我想确保我走的是最有效的路线。

编辑:我在这里有一个大问题,那就是向用户显示进度的最佳方式。一旦用户提交了内容,他就会被带到一个新页面,并可以通过批标识符查看状态。是否需要MSMQ或NServiceBus来通知用户?这似乎是请求/确认/推送范式的变体?

如何在ASP.NET Web API中对后台任务进行排队

IMHO,您的ASP.NET Web API应用程序不应该自己运行这些后台任务。它应该只负责接收请求,将其放入队列中(如您所示),并返回指示接收消息成功或失败的响应。对于这种方法,您可以使用各种消息传递系统,如RabbitMQ。

至于通知,您有几个选择。您可以有一个端点,客户端可以检查处理是否完成。或者,你可以提供一个流式API端点,你的客户端可以订阅。这样,客户端就不必轮询服务器;服务器可以通知连接的客户端。ASP.NET Web API有一个很好的方法来实现这一点。以下博客文章解释了如何:

  • 带有ASP.NET Web API和Knockout.js的本地HTML5推送通知

对于这种类型的服务器到客户端通知,您也可以考虑SignalR。

ASP.NET Web API应用程序的后台任务之所以困难,是因为您有责任使AppDomain保持活动状态。这是一个麻烦,尤其是当您在IIS下托管时。以下博客文章很好地解释了我的意思:

  • 从ASP.NET请求提前返回
  • ASP.NET中实现递归后台任务的危险

这是一个NuGet包,名为HangFire-https://github.com/HangfireIO/Hangfire.这些任务甚至在apppool回收之后仍然存在。

我喜欢@Todd的解决方案。只是为了完整起见,但还有另一个选项尚未提及:

HostingEnvironment.QueueBackgroundWorkItem(cancellationToken =>
{
    // Some long-running job
});

注:

当ASP.NET必须回收时,它会通知后台工作(通过设置CancellationToken),然后等待30秒等待工作完成。如果后台工作没有在该时间段内完成,则工作将神秘地消失。

并且避免在这里使用带有注入DbContext的服务方法,因为这不起作用。

来源:MariusSchulz和StephenCleary

如果使用Asp.net Core,则可以使用IHostService。