当 Azure 应用服务扩展我的 Web API 时,SemaphoreSlim 是否会同时两次保护代码免受 运行 的影响?

Will SemaphoreSlim protect code from running twice simultaneously when Azure App Service scales out my Web API?

我在 Azure App Service 上有一个 ASP .Net Core 5 Web API 运行ning。 它包含每天 运行 一次的服务,大约在午夜。 所以我有一个 System.Threading.Tasks.Timer,运行 每小时一次。如果是在午夜和凌晨 1 点之间,它将启动服务。 该服务大约需要一分钟才能完成,并且是一个执行一些数据库操作的循环。

前几天,出于某种原因,它 运行 两次。因此,虽然它是 运行ning,但在它完成之前,它同时 运行 第二个实例。

我不明白为什么会这样。然后我记得我最近将 Azure App Service 设置为在 CPU 或内存利用率增加到 70% 以上时最多扩展到 3 个实例。然后我想,这会不会是它 运行 两次的原因?虽然它是 运行ning,但 CPU 或内存利用率超过 70%,因此 Azure App Service 创建了我的 Web API 的第二个实例,然后触发了计时器,它看到它是在午夜和凌晨 1 点之间,所以 运行 服务?

我想,好吧,我想这是可能的。所以,我认为该服务需要对此进行保护。它不应该允许它的两个实例同时 运行(或者实际上,在任何给定的 24 小时内)。

起初我想到了使用Lock/Monitor。但是我的服务是异步的,并且在一些地方使用了 await 关键字,所以这不适用于 Lock/Monitor。所以我最终使用了 SemaphoreSlim。然而,根据我的研究,SemaphoreSlim 只能防止内部线程执行两次相同的代码。它不能防止外部线程(我相信信号量或互斥量的方式)。

所以,为了总结这个相当冗长的 post,我想知道当 Azure App Service 增加我的 Web 的实例计数时,SemaphoreSlim 是否真的会保护我的服务免于同时执行两次 API .由于它本质上是我的 API 运行ning 的两个独立实例(据我所知),第二个实例是否会被视为外部线程,因此不受 SemaphoreSlim 监控?

谢谢

SemaphoreSlim 不会保护您的过程免受 运行同时跨越多个服务实例的影响。 SemaphoreSlim 确实会将您的代码 锁定在应用程序的域内 ,但向外扩展会创建一个具有自己进程的 Web 应用程序的全新实例。

您可以通过创建分布式锁来解决这个问题,也许是通过数据库或缓存查找,或者您可以重新设计您的应用程序,以 运行 代码,这可能不会 运行 同时,通过一个单独的过程。考虑是否可以将其实现为 Azure function, or a webjob marked as a singleton.