如何在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来通知用户?这似乎是请求/确认/推送范式的变体?
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。