【问题标题】:What is a good API architecture to handle long running tasks? [closed]什么是处理长时间运行任务的良好 API 架构? [关闭]
【发布时间】:2018-08-13 19:44:38
【问题描述】:

我正在尝试实现一个基于 ASP.NET Core 的 Web 服务,该服务将通过 ARM 模板和适用于 .NET 的 Azure SDK 部署 Azure 资源。

问题是,根据我的测试,一些操作最多可能需要三到四分钟才能完成。我没有设计需要这么长时间才能完成某事的 API 的经验。

所以我想做的事情如下。

  1. 当 API get 请求提供资源时,我将请求信息放入队列中。
  2. 我返回一个带有票号的 200,让调用者监控进度,调用者可以通过调用另一个端点来监控进度。
  3. 我使用网络作业创建资源请求,并更新数据库中的信息。
  4. 当调用者调用端点以获取有关资源部署进度的反馈时,我现在可以提供更新的信息(成功或失败)。

我不确定这种架构,因为我以前从未做过类似的事情。我正在考虑使用 Azure 队列来组织传入的请求,使用 Azure 表在进行部署时放置有关请求的信息,并在创建请求时使用 Azure WebJobs。

这是一个足够体面的架构还是我应该考虑使用其他技术或模式来做到这一点?我不确定如何处理这种情况,欢迎提出任何意见。

【问题讨论】:

  • 2) 改为返回202 Accepted,以明确表示“嘿,我有你的东西,我稍后再处理”。代替票号,返回带有结果的Location 标头,如果您对客户端何时应该“回电”有一个粗略的想法,请添加Retry-after 标头。客户端,当 Location 不再返回 404 时,它应该尝试渲染结果或启动处理这些结果的任何逻辑。

标签: .net api azure architecture


【解决方案1】:
  1. 我返回一个带有票号的 200,让调用者监控进度,调用者可以通过调用另一个端点来监控进度。

改为返回202 Accepted,以明确表示“嘿,我有你的东西,我稍后再处理”。

返回一个Location 标头而不是票号,如果您对客户端何时应该“回电”有一个粗略的想法,请添加一个Retry-after 标头。

客户端,当位置 URL 不再返回 404 时,客户端 UI 应尝试呈现结果,或者 - 如果没有 UI - 启动处理这些结果的任何逻辑。

我正在考虑使用 Azure 队列来组织传入的请求 [...]

我支持这个决定。否则,您将只是从头开始重新实现持久性、重试和不良参与者处理,我们都知道最好的代码是别人的代码。

使用 Azure 队列,您需要 implement your own poison message logic,Service Bus 开箱即用。

【讨论】:

    【解决方案2】:

    此问题正在征求意见,可能已关闭。但在此之前,这是一个非常合理的计划,适合您要完成的工作。我亲自实现了一个非常相似的架构,它在重负载下也能很好地支撑起来。几点建议:

    • 确保正确选择队列实现。您的选择是服务总线队列或存储队列。你可以find a great comparison here

    • Azure 表是可以真正扩展的廉价(并且可以快如闪电)存储。但是您只有一个分区键和一个行键可以使用。如果这足以满足您的要求,那就太好了!否则,请考虑 CosmosDB 表或 Azure SQL DB 之类的东西。

    • 对于长时间运行的处理,请考虑如果您的 Web 作业崩溃并且您必须重新开始处理队列消息时会发生什么。如果有多个不应该重复的处理阶段,您需要对此进行计划。否则,ServiceBusTrigger 内置了很好的重试逻辑。

    【讨论】:

    • “但是你只有一个分区键和一个行键可以使用” - 你能再澄清一下吗?