Quartz.NET配置问题:从Key Vault取连接字符串后持久化失效
如何通过依赖项配置Quartz.NET从Key Vault获取连接字符串并实现持久化存储
问题背景
需要通过依赖注入访问SecretClient,从Key Vault中动态获取PostgreSQL连接字符串来配置Quartz.NET的持久化存储,但遇到以下问题:
- Quartz.NET的流畅配置API无法直接访问DI容器中的依赖项
- 通过
PostConfigure修改QuartzOptions后,DI中能拿到正确配置,但Quartz并未实际使用该配置,导致作业无法写入数据库
现有尝试
- 流畅API配置限制:无法在
AddQuartz的配置委托中访问SecretClient等依赖项
services.AddQuartz(op => { op.UsePersistentStore(pso => { pso.UsePostgres(apo => { apo.ConnectionString = ...; // 无法从DI获取连接字符串 }); }); });
- QuartzOptions绑定配置:通过appsettings配置可行,但需要硬编码连接字符串,不符合Key Vault管理需求
{ "Quartz": { "quartz.dataSource.myquartzstore.provider": "Npgsql", "quartz.dataSource.myquartzstore.connectionString": "connection-string-for-environment" } }
- 自定义连接字符串提供者:实现了
PostgreDbConnectionProvider,根据环境从本地配置或Key Vault获取连接字符串
public class PostgreDbConnectionProvider(SecretClient secretClient, IHostEnvironment hostEnvironment, IOptions<PostgreSqlOptions> postgreSqlOptions) : IPostgreDbConnectionProvider { public string GetConnectionString() { var isLocalDev = hostEnvironment.IsEnvironment("LocalDevelopment"); var secretId = postgreSqlOptions.Value.ConnectionStringSecretIdentifier; var localConnStr = postgreSqlOptions.Value.ConnectionString; return isLocalDev ? localConnStr : secretClient.GetSecret(secretId).Value.Value; } }
- PostConfigure修改QuartzOptions:修改后的配置在DI中可读取,但Quartz未生效,作业无法写入数据库
services.AddOptions<QuartzOptions>() .BindConfiguration("Quartz") .PostConfigure<IPostgreDbConnectionProvider>((op, connProvider) => { var connStr = connProvider.GetConnectionString(); op.Add("quartz.dataSource.myquartzstore.connectionString", connStr); // 其他配置项... });
解决方案
核心问题是Quartz.NET在AddQuartz阶段就完成了配置初始化,后续修改QuartzOptions无法同步到Quartz内部配置。正确做法是在AddQuartz时直接从DI获取依赖项,动态配置连接字符串:
1. 注册自定义连接提供者
services.AddSingleton<IPostgreDbConnectionProvider, PostgreDbConnectionProvider>();
2. 使用带IServiceProvider的AddQuartz重载
在配置Quartz时直接从DI容器获取IPostgreDbConnectionProvider,拿到动态连接字符串:
services.AddQuartz((serviceProvider, options) => { // 从DI获取连接字符串提供者 var connProvider = serviceProvider.GetRequiredService<IPostgreDbConnectionProvider>(); var connectionString = connProvider.GetConnectionString(); // 配置持久化存储 options.UsePersistentStore(persistOptions => { persistOptions.UsePostgres(postgresOptions => { postgresOptions.ConnectionString = connectionString; }); // 使用JobStoreTX实现持久化(根据需求选择) persistOptions.UseJobStore<JobStoreTX>(); }); // 其他Quartz全局配置 options.SchedulerName = "MyApplicationScheduler"; options.ThreadPool.MaxConcurrency = 10; options.UseSystemTextJsonSerializer(); });
3. 注册Quartz托管服务
确保Quartz作为后台服务运行:
services.AddQuartzHostedService(hostedOptions => { hostedOptions.WaitForJobsToComplete = true; });
验证
配置完成后,调用scheduler.ScheduleJob时,作业会被正确写入PostgreSQL数据库。同时检查作业定义是否开启持久化:
var jobDetail = JobBuilder.Create<SimpleLoggerJob>() .StoreDurably() // 必须开启持久化 .Build();
内容的提问来源于stack exchange,提问作者milorad
相关产品推荐
相关产品推荐

