我有一个webapi,旨在以队列方式处理报告。该应用程序采取的步骤如下:
我正在考虑使用Entity Framework来创建排队项目的数据库,例如:
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是否有更有效的方法,而不是不断轮询数据库并逐个提取待处理的项目?我之前没有使用过队列。
一种想法是创建一个任务队列,并在一个单独的线程上处理所有挂起的任务。与Most efficient way to process a queue with threads有些相似,但我想确保我走的是最有效的路线。
编辑: 我在这里遇到的一个重要问题是向用户显示进度的最佳方式。一旦用户提交内容,他就会进入新页面,并可以按批次标识符查看状态。 MSMQ是必需的,还是NServiceBus,以便通知用户?这似乎是REquest / Acknowledge / Push范式的一种变体?
答案 0 :(得分:25)
至于通知,您有几个选择。您可以拥有一个客户端可以检查处理是否完成的端点。或者,您可以提供客户端可以订阅的流API端点。这样,客户端就不必轮询服务器;服务器可以通知连接的客户端。 ASP.NET Web API有一个很好的方法。以下博客文章解释了如何:
您还可以考虑SignalR此类服务器到客户端通知。
ASP.NET Web API应用程序很难执行后台任务的原因是您有责任让AppDomain保持活动状态。这是一个麻烦,尤其是当您在IIS下托管时。以下博客文章解释了我的意思:
答案 1 :(得分:5)
它是一个NuGet包,它被称为HangFire - https://github.com/HangfireIO/Hangfire。这些任务仍然存在于apppool回收之外。
答案 2 :(得分:2)
我喜欢@Todd的解决方案。仅仅为了完整起见,但还有另一个选项尚未提及:
HostingEnvironment.QueueBackgroundWorkItem(cancellationToken =>
{
// Some long-running job
});
注意:
“当ASP.NET必须回收时,它将通知后台工作(通过设置CancellationToken),然后等待最多30秒才能完成工作。如果后台工作未在该时间范围内完成,这项工作将神秘地消失。“
并且避免在此处使用带有注入的DbContext的服务方法,因为这不起作用。
答案 3 :(得分:0)
如果您使用Asp.net Core,则可以使用IHostService。