18

我有一个 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?这似乎是请求/确认/推送范式的变体?

4

4 回答 4

27

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

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

您还可以考虑将SignalR用于此类服务器到客户端的通知。

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

于 2013-02-05T16:20:39.537 回答
7

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

于 2014-11-17T13:30:19.470 回答
2

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

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

笔记:

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

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

资料来源: MariusSchulzStephenCleary

于 2016-02-18T10:59:57.520 回答
0

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

于 2018-09-26T07:50:08.160 回答