【问题标题】:Handling long blocking API calls in ASP.NET Core在 ASP.NET Core 中处理长阻塞 API 调用
【发布时间】:2022-02-23 08:32:25
【问题描述】:

我正在构建一个 API,它将处理立即执行大量工作的 http 调用。

例如,在一个控制器中,有一个操作(Post 请求)将在主体中获取数据,并执行一些应该立即完成的处理,但会持续大约 1 到 2 分钟。

我使用 CQRS 和 Mediatr,在这个发布请求中,我调用一个命令来处理处理。

考虑到这一点,我希望发布请求启动命令,然后向用户返回 Ok,尽管命令仍在后台运行。一切完成后,用户将收到电子邮件通知。

有人知道实现此目的的最佳实践吗?

虽然我使用 MediatR,将请求发送到处理程序,但调用不会并行执行。

[HttpPost]
public async Task<IActionResult> RequestReports([FromBody] ReportsIntent reportsIntent)
{
     await _mediator.Send(new GetEndOfWeekReports.Command(companyId, clientId, reportsIntent));
     return Ok();
}

【问题讨论】:

    标签: asp.net-core background cqrs mediatr


    【解决方案1】:

    有人知道实现此目的的最佳实践吗?

    Yes(如我的博客所述)。

    您需要我所说的“基本分布式架构”。具体来说,您至少需要:

    1. 一个持久队列。这里的“持久”是指“在磁盘上;不在内存中”。
    2. 后端处理器。

    因此,web api 会将请求中的所有必要数据序列化为队列消息并将其放入队列中,然后返回给客户端。

    然后后端处理器从该队列中检索工作并执行实际工作。在您的情况下,这项工作以发送电子邮件结束。

    在某种程度上,这有点像 MediatR,但显式地退出进程并使用磁盘队列和一个单独的进程作为您的处理程序。

    【讨论】:

    • 谢谢 我浏览了你的一些帖子,但代码不多。我猜我猜对持久工作部分使用hangfire会完成预期的工作?
    • @DamienDoumer:是的,with caveats
    • 谢谢。会试试看。我提出了另一种方法,使用 System.Threading.Tasks.Channels 对要由后台服务运行的任务进行排队。我将深入研究这两种方法,看看哪种方法最合适。
    • @DamienDoumer:通道是内存队列,因此它们不是正确的解决方案——假设您总是希望完成后台工作。
    • 好的,谢谢。那我就坚持挂火。
    【解决方案2】:

    我会处理需要一些时间的 API 调用,而不是可以直接完成的调用。

    当我执行需要时间的 API 调用时,我会将它们排队并在后端处理它们。

    典型的 API 调用可能如下所示:

    POST http://api.example.com/orders HTTP/1.1
    Host: api.example.com
    
    HTTP/1.1 201 Created
    Date: Fri, 5 Oct 2012 17:17:11 GMT
    Content-Length: 123
    Content-Type: application/json
    Location: http://poll.example.com/orders/59cc233e-4068-4d4a-931d-cd5eb93f8c52.xml
    ETag: "c180de84f951g8" 
    
    { uri: 'http://poll.example.com/orders/59cc233e-4068-4d4a-931d-cd5eb93f8c52.xml'}
    

    返回的 URL 是一个唯一的 URL,客户端可以在其中轮询/查询以了解作业的状态。

    当客户端查询这个 URL 时,它可能看起来像这样:

    当它稍后完成时,结果将类似于:

    其中 dataurl 是指向客户端可以下载的结果/报告的链接。

    【讨论】:

    • 谢谢,请问你们是怎么排队的?我想到的是hangfire。但是你有不同的方法吗?
    • 我在后端实现了一个自定义队列解决方案......在 Hangfire 中?我不知道..您不希望 HTTP 请求需要几分钟才能完成,因为例如客户端可能会超时....
    • 谢谢,我会尝试在 asp.net core 中使用 Channels 和后台服务来完成这个,
    猜你喜欢
    • 2011-05-02
    • 1970-01-01
    • 2019-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-11
    • 2021-12-25
    • 1970-01-01
    相关资源
    最近更新 更多