在长时间运行的工作中防止更改
Posted
技术标签:
【中文标题】在长时间运行的工作中防止更改【英文标题】:Prevent Changes during long running job 【发布时间】:2020-01-09 04:12:44 【问题描述】:我们的 Web 应用程序使用在 loab 平衡器和 Angular 客户端上运行的 .net-core Web api。我们使用 EF 核心访问数据库。 我们有一个长时间运行的后台任务,它会进行大量计算,大约需要 2-3 小时才能完成,但每年只会由应用程序管理员启动 3-4 次。 在作业运行时,我们希望阻止用户添加/编辑/删除数据,我们的客户告诉我们,如果应用程序在此期间不可用,这甚至可以,因为他们通常会在一夜之间完成。 最简单的方法是在作业运行时将用户重定向到信息页面,但如果任务正在运行,我发现无法实际获取信息。
我可以设置一个标记来判断作业是否正在运行,然后在每次请求时检查该标记,但我发现无法访问应用程序范围的状态。
我无法将标志保存到数据库,因为在作业结束时(约 1 小时)提交事务时,我们无法从数据库中读取数据
最让我困惑的是,我还没有找到一篇文章或问题关于这样的问题对我来说似乎不太奇怪,所以我想我遗漏了一些非常明显的东西。
【问题讨论】:
这是题外话,我猜,但你可以使用专用的 Redis 服务器来存储这个标志 使用hangfire代替后台任务并检查作业是否正在运行?如果您在负载均衡器后面,如何保证只有 1 个实例在执行作业? 虽然它确实在后台运行,但我们确实使用 signalR 将进度推送到 UI,所以我不知道 hangfire 是否适用。 【参考方案1】:最简单的方法是将“维护模式”的值存储在服务器上的 Singleton 类中。 (不需要数据库调用)。只要服务器正在运行,该值就会一直存在。
【讨论】:
他们谈到了负载平衡。你不能在不同的机器上共享单例。 啊,抱歉,我完全跳过了负载平衡器部分:-s 也许一个单独的数据库来存储值?或者可能使用分布式缓存机制,如alachisoft.com/ncache 所以只需要使用分布式缓存。这个答案的核心仍然有效。 我希望有更简单的方法,但分布式缓存似乎是唯一的选择。【参考方案2】:如果分布式缓存(如前所述)不是一个选项,您可以在(唯一)命名事务中运行长时间运行的任务,然后检查活动事务的检查列表以确定任务是否仍在运行。
【讨论】:
【参考方案3】:这完全取决于您的设置,但解决此问题的一种简单方法可能是让长期运行的作业负责在您的网站运行时转移流量,然后在完成后撤消该操作。
例如,如果您在 IIS
中使用老式 .NET 站点运行此作业,则作业可能会将 app_offline.htm
文件放入站点文件夹中,运行,然后再次删除它。您的设置有所不同,但如果您可以对负载均衡器执行类似的操作(将其配置为提供一些静态文件,而不是将请求路由到您的服务器),那么它可能适合您。
【讨论】:
以上是关于在长时间运行的工作中防止更改的主要内容,如果未能解决你的问题,请参考以下文章