Web API 2 返回 OK 响应但在后台继续处理

Posted

技术标签:

【中文标题】Web API 2 返回 OK 响应但在后台继续处理【英文标题】:Web API 2 return OK response but continue processing in the background 【发布时间】:2015-01-19 13:04:48 【问题描述】:

我已经为 shopify 创建了一个 mvc web api 2 webhook:

public class ShopifyController : ApiController

    // PUT: api/Afilliate/SaveOrder
    [ResponseType(typeof(string))]
    public IHttpActionResult WebHook(ShopifyOrder order)
    
        // need to return 202 response otherwise webhook is deleted
        return Ok(ProcessOrder(order));
    

ProcessOrder 循环遍历订单并将详细信息保存到我们的内部数据库。

但是,如果这个过程花费的时间太长,那么 webhook 会再次调用 api,因为它认为它已经失败了。有什么方法可以先返回ok 响应,然后再进行处理?

有点像当您在 mvc 控制器中返回重定向并可以选择在重定向后继续处理其余操作。

请注意,我将始终需要返回 ok 响应,因为 Shopify 已决定在 webhook 失败 19 次时删除它(处理时间过长被视为失败)

【问题讨论】:

您是否尝试过实现一种 Job,它将在后台处理您的数据并立即返回响应给 shopify?您可以查看此答案以获取详细信息:***.com/questions/14710822/… 我正在将该方法转换为某种异步任务以查看是否可行,我认为问题更多是关于是否有内置版本返回 ok 并继续而不必添加第三方库 异步处理可以帮助您提高操作的性能,但它认为它不会帮助您在操作完成之前返回响应。无论如何,我不知道有任何内置工具 【参考方案1】:

我已经设法通过使用Task 异步运行处理来解决我的问题:

    // PUT: api/Afilliate/SaveOrder
    public IHttpActionResult WebHook(ShopifyOrder order)
    
        // this should process the order asynchronously
        var tasks = new[]
        
            Task.Run(() => ProcessOrder(order))
        ;

        // without the await here, this should be hit before the order processing is complete
        return Ok("ok");
    

【讨论】:

ProcessOrder() 在执行时被随机终止,您可以吗?因为这是您使用Task.Run() 或任何其他类型的后台处理在您的ASP.NET 工作进程中 打开的蠕虫罐。如果是这样,那么这就是要走的路。如果没有,请将工作卸载到专用程序,如 Windows 服务。阅读comment by @Vsevolod 中提供的链接。 @CodeCaster 公平地说,它只是一个临时的 api,所以我不太担心编写一个完整的其他服务来处理它,并且很高兴忍受使用后台进程的限制 @CodeCaster 你能告诉我更多关于为什么你说 ProcessOrder() 可能会在执行时随机终止吗? @user1431072 因为如果您的应用程序池被回收,您自己启动的后台线程很容易被终止。阅读上面的 cmets 和链接。 只是为了让您知道其他 cmets 是正确的,线程将随机终止,并且无论它正在做什么,如果长时间运行,可能无法完成。我一直在尝试自己寻找解决方案。我认为 CodeCaster 说得最好,您必须将工作转移到不同的程序。这也是我试图弄清楚自己的原因【参考方案2】:

有几个选项可以做到这一点:

    让像 HangfireQuartz 这样的任务运行程序运行实际处理,您的网络请求只是启动任务。 使用队列(如RabbitMQ)来运行实际进程,而Web 请求只是将消息添加到队列中……注意这可能是最好的,但可能需要一些重要的设置知识。 虽然可能不完全适用于您的具体情况,因为您有另一个进程等待请求返回...但如果您没有,您可以使用javascript AJAX 在后台启动该进程,也许您可​​以关闭对该请求的重试...仍然使请求在后台继续进行,因此可能不完全是您的那杯茶。

【讨论】:

【参考方案3】:

Task.Run(() => ImportantThing() 不是一个合适的解决方案,因为它会使您面临许多潜在问题,其中一些已经在上面解释过。 Imo,其中最邪恶的可能是工作进程上未处理的异常,实际上可以直接杀死你的工作进程,而在事件日志之外没有任何错误的痕迹或在操作系统上捕获的东西,如果这甚至是可用的。不好。

有许多更合适的方法来处理这种情况,例如切换服务总线或实现HostedService

https://docs.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services?view=aspnetcore-6.0&tabs=visual-studio

【讨论】:

以上是关于Web API 2 返回 OK 响应但在后台继续处理的主要内容,如果未能解决你的问题,请参考以下文章

如何将 ASP.NET Core 5 Web API 控制器操作的失败模型验证结果包装到另一个类中并将响应返回为 OK

koa返回前端响应后,后台静默做其他操作

koa返回前端响应后,后台静默做其他操作

不可接受的响应 (406) 消息 Asp.NET 代码 Web API (C#) - .NET 5.0

如何测试返回 Ok(object) 的 ASP.NET Core 2.2 Web API GET IActionResult?

Web API接口