关于托管在 Azure 应用服务横向扩展实例中的 Quartz.NET 的注意事项

Considerations about Quartz.NET hosted inside scaled out instance of Azure App Service

如何处理 API 的 Quartz 配置,该 API 在 ASP.NET Core 中创建并托管在扩展到多个实例的 Azure App Service 中?

API 目前始终托管在单个 IIS 应用程序中,因此 Quartz 配置如下所示,未使用集群配置

private static NameValueCollection SchedulerConfiguration(IConfiguration configuration)
{
    var schedulerConfiguration = new NameValueCollection();
    schedulerConfiguration["quartz.jobStore.type"] = "Quartz.Impl.AdoJobStore.JobStoreTX, Quartz";
    schedulerConfiguration["quartz.jobStore.driverDelegateType"] = "Quartz.Impl.AdoJobStore.StdAdoDelegate, Quartz";
    schedulerConfiguration["quartz.jobStore.tablePrefix"] = "QRTZ_";
    schedulerConfiguration["quartz.jobStore.dataSource"] = "default";
    schedulerConfiguration["quartz.dataSource.default.connectionString"] = configuration["ConnectionString"];
    schedulerConfiguration["quartz.dataSource.default.provider"] = "SqlServer";
    schedulerConfiguration["quartz.serializer.type"] = "json";
    return schedulerConfiguration;
}

并且它利用 QuartzHostedService 来处理预定的后台作业

services.AddHostedService<QuartzHostedService>();

我做了一个小实验,将 API 部署到 Azure App Service 实例中,然后在 API 中创建了一个 Quartz 作业,并在触发前将多个实例扩展到 4 个解雇了。 我的假设是,如果不对上述配置做任何更改,作业将执行 4 次,因为当新的 3 个实例启动时,它们都会从数据库中读取作业详细信息并注册触发器以在特定时间触发。但令我惊讶的是,这个工作只执行了一次。

  1. 知道作业只执行一次的原因吗?
  2. 在横向扩展的 Azure 应用服务中托管 Quartz 调度程序时,我是否应该利用集群配置?
  1. 我认为这可能只是纯粹的运气,如果您的作业 运行 很快,它们可能 运行 仅由集群中的单个实例执行。但是如果没有集群设置,两个节点可能会向 运行 执行相同的作业并导致数据库更新冲突。

  2. 是的,当使用基于数据库的锁时会有轻微的性能损失,但这是您可以安全地 运行 繁忙实例的唯一方法。

我还建议您查看 ASP.NET Core integration package。它有助于编译安全配置,例如我可以看到您现在为 SQL 服务器使用了错误的(低效的)委托,有单独的 SqlServerDelegate。