[英]Start extremely long running processes through a REST request
我在一家自动化公司工作,所以我们为工业自动化创建流程。 以前这种自动化是在机器方面完成的,但我们正在慢慢过渡到使用 c# 控制机器。
在我目前的项目中,一天的制作大约需要 2 个小时。 工厂的操作员有一个我们在 c# 中使用 asp.net 核心 MVC 创建的 Web 界面,他们可以在其中启动/暂停/停止此生产过程。
当开始这个过程时,我们等待控制器中的一个函数,它基本上是一个控制这个 2 小时长的生产过程的 while 循环。
现在的问题是,当我发出 REST 请求以开始生产时,此请求需要 2 小时才能完成,我希望此请求立即完成,并且生产过程在我的 asp.net 核心应用程序的后台开始。
首先,我想我可以省略等待,只需在我的控制器中执行此操作(简化代码):
_ = _productionController.StartLongProcess(); // This contains the while loop
return Ok();
但是由于 _productionController 是有作用域的,并且它的所有依赖项也是如此,因此当方法返回时这些会立即被处理掉,例如我无法再访问我的数据库。
该流程应该能够不断地与我们的数据库对话,以保存有关生产流程的信息,以防万一出现故障,这样我们就可以从中断的地方继续进行。
我现在要问你的问题是,我们是否以错误的方式解决这个问题? 我想在 asp.net 控制器中启动这些长时间运行的进程是不好的做法。
即使 REST 请求已经结束,我如何确保在这个长时间运行的过程中始终可以访问我的 DatabaseContext。 仅为此方法创建单独的范围?
从 ASP.NET Core 2.1 开始,执行此操作的正确方法(在 asp.net 中)是扩展BackgroundService
(或实现IHostedService
)。
传入的请求可以告诉后台服务启动长时间运行的操作并立即返回。 您当然需要处理在现有请求完成之前发送重复请求或发送新请求的情况。
文档页面有一个示例,其中BackgroundService
读取队列的命令并一次处理一个。
即使 REST 请求已经结束,我如何确保在这个长时间运行的过程中始终可以访问我的 DatabaseContext。 仅为此方法创建单独的范围?
是的,创建一个单独的范围。
我现在要问你的问题是,我们是否以错误的方式解决这个问题? 我想在 asp.net 控制器中启动这些长时间运行的进程是不好的做法。
我们过去做过类似的事情。 只要容错(尤其是 wrt 应用程序重新启动)和幂等性内置到长时间运行的操作的逻辑中,您就应该很高兴。
REST 请求预计很短,最多几秒钟。 所以这里的最佳实践是将长时间运行的任务卸载到后台服务,并返回一个令牌,如果操作已经完成,您可以在其中轮询服务。
后台服务可以是 Net Core 中的 BackGroundWorker。 这很容易,但不是真正的容错,所以某种数据库和重试逻辑可能是好的。
如果您在 Intranet 中,您还可以转而使用固有的异步协议,例如 RabbitMQ,您可以在其中发送 StartOperation 消息,然后在流程完成时接收 Started 消息。
以下是我对您发布的问题的理解:
几个要点:
ConfigureAwait(false)
避免在当前同步上下文中显式重入,这对性能更好Task.Wait
或Task.Result
, Task.Result
甚至可能导致死锁ASP.NET关于长时间运行的操作,以下是选项
IObservable
,可以帮助在处理完成时通知客户端如果客户端想要定期上来并检查请求的状态,那么数据库持久性很重要,它可以定期更新,并且可以检查长时间运行的进程的状态。
另一种选择是使用 Hangfire。 它将允许您将要执行的工作排入持久存储,例如 SQL Server、MSMQ、Redis,具体取决于您的基础架构中的内容。 然后,该作业将由一个也可以在 ASP.NET 进程或 Windows 服务中运行的工作人员接手。 它也是分布式的,因此您可以运行多个工作程序实例。 还支持重试失败的作业,并有一个仪表板来查看作业。 最棒的是,它是免费的!
var jobId = BackgroundJob.Enqueue(() => ExecuteLongRunningProcess(parameter1));
我现在要问你的问题是,我们是否以错误的方式解决这个问题? 我想在 asp.net 控制器中启动这些长时间运行的进程是不好的做法。
一般来说,是的。 理想情况下,ASP.NET 服务内部没有任何长时间运行的进程 - 或者至少,没有无法轻松快速关闭的长时间运行进程。
通过添加具有单独后台处理器的持久队列,最可靠地实现 HTTP 请求之外的工作(即请求外部代码)。 “后台处理器”可以是 Win32 服务,甚至可能在同一台机器上。 在这种架构下,HTTP 请求将请求放入队列,处理器从队列中选取请求并执行它们。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.