ASP.NET Core Web API发布IIS后Quartz后台任务失效求助
问题:ASP.NET Core部署IIS后Quartz.NET调度任务未执行
基于Quartz.NET开发的后台调度服务在本地运行正常,但发布至IIS服务器后,Swagger页面可正常访问,发布过程无异常,但后台调度任务完全无法执行。核心实现代码如下:
public class NotificationJob : IHostedService { readonly ILogger<NotificationJob> _logger; public NotificationJob(ILogger<NotificationJob> logger) { _logger = logger; } public async Task StartAsync(CancellationToken cancellationToken) { _logger.LogInformation("Service started..!"); await NotificationJob1(); // ... } public Task StopAsync(CancellationToken cancellationToken) { _logger.LogInformation("Service stopped..!"); return Task.CompletedTask; } private async Task NotificationJob1() { var schedulerFactory = new StdSchedulerFactory(); var scheduler = await schedulerFactory.GetScheduler(); await scheduler.Start(); // Define the job var job = JobBuilder.Create<BackgroundWorkerJob>() .WithIdentity("BackgroundWorkerJob", "DefaultGroup") .Build(); // Define multiple triggers with different time intervals var triggers = new List<ITrigger> { //--------------------------------------- NOTIFICATION 0 ---------------------------------------- TriggerBuilder.Create() .WithIdentity("BackgroundWorkerJobTrigger0", "DefaultGroup") .StartAt(DateBuilder.TodayAt(23,58,00)) // 2:19 PM Today .WithSimpleSchedule(x => x.WithIntervalInHours(24) // Repeat every 24 hours .RepeatForever()) .Build(), //--------------------------------------- NOTIFICATION 1 ---------------------------------------- TriggerBuilder.Create() .WithIdentity("BackgroundWorkerJobTrigger1", "DefaultGroup") .StartAt(DateBuilder.TodayAt(23,59,0)) // 6:30 PM Today .WithSimpleSchedule(x => x.WithIntervalInHours(24) // Repeat every 24 hours .RepeatForever()) .Build(), //--------------------------------------- NOTIFICATION 2 ---------------------------------------- TriggerBuilder.Create() .WithIdentity("BackgroundWorkerJobTrigger2", "DefaultGroup") .StartAt(DateBuilder.TodayAt(24,00, 0)) // 6:30 PM Today .WithSimpleSchedule(x => x.WithIntervalInHours(24) // Repeat every 24 hours .RepeatForever()) .Build(), //--------------------------------------- NOTIFICATION 3 ---------------------------------------- TriggerBuilder.Create() .WithIdentity("BackgroundWorkerJobTrigger3", "DefaultGroup") .StartAt(DateBuilder.TodayAt(15,32, 0)) // 6:30 PM Today .WithSimpleSchedule(x => x.WithIntervalInHours(24) // Repeat every 24 hours .RepeatForever()) .Build(), // Add more triggers as needed }; // Schedule the job with multiple triggers await scheduler.ScheduleJob(job, triggers, true); // 'true' means to replace existing triggers if any } }
解决方案
1. 调整IIS应用池核心配置
- 将应用池启动模式设置为
AlwaysRunning,避免IIS因闲置自动回收进程 - 开启应用池预加载功能,确保站点启动时立即初始化后台服务
- 确认应用池的.NET CLR版本设置为
无托管代码(适用于ASP.NET Core 3.1及以上版本)
2. 改用Quartz.NET官方依赖注入方式
当前手动创建StdSchedulerFactory的方式容易在IIS进程回收时丢失调度上下文,建议通过DI注册Quartz服务:
// 在Program.cs中注册Quartz相关服务 builder.Services.AddQuartz(q => { // 使用.NET依赖注入管理Job实例 q.UseMicrosoftDependencyInjectionJobFactory(); // 注册后台执行的Job q.AddJob<BackgroundWorkerJob>(opts => opts.WithIdentity("BackgroundWorkerJob", "DefaultGroup")); // 为Job添加第一个触发器 q.AddTrigger(opts => opts .ForJob("BackgroundWorkerJob", "DefaultGroup") .WithIdentity("BackgroundWorkerJobTrigger0", "DefaultGroup") .StartAt(DateBuilder.TodayAt(23, 58, 00)) .WithSimpleSchedule(x => x.WithIntervalInHours(24).RepeatForever())); // 依次添加其他触发器(示例为Trigger1) q.AddTrigger(opts => opts .ForJob("BackgroundWorkerJob", "DefaultGroup") .WithIdentity("BackgroundWorkerJobTrigger1", "DefaultGroup") .StartAt(DateBuilder.TodayAt(23, 59, 00)) .WithSimpleSchedule(x => x.WithIntervalInHours(24).RepeatForever())); // 注意:修正Trigger2的时间配置,24点应改为0点 q.AddTrigger(opts => opts .ForJob("BackgroundWorkerJob", "DefaultGroup") .WithIdentity("BackgroundWorkerJobTrigger2", "DefaultGroup") .StartAt(DateBuilder.TodayAt(0, 00, 00)) .WithSimpleSchedule(x => x.WithIntervalInHours(24).RepeatForever())); }); // 注册Quartz托管服务,确保应用停止时等待任务完成 builder.Services.AddQuartzHostedService(q => q.WaitForJobsToComplete = true);
之后删除原NotificationJob中手动初始化调度器的代码,直接依赖Quartz的托管服务即可。
3. 修复时间配置错误
代码中DateBuilder.TodayAt(24,00,0)是无效参数,小时范围为0-23,需改为DateBuilder.TodayAt(0,00,0)表示午夜12点。
4. 排查进程回收与日志
- 检查IIS应用池的回收规则,禁用不必要的定时回收,或调整回收时间至任务空闲时段
- 补充日志输出:在
BackgroundWorkerJob的Execute方法中记录执行日志,在调度初始化过程中添加调度器启动、触发器注册的日志,通过日志确认调度是否正常初始化 - 确认服务器系统时间与本地一致,避免触发器启动时间设置偏差
5. 验证权限配置
确保IIS应用池的运行账号拥有执行Job业务逻辑所需的权限(如文件读写、数据库访问、第三方API调用等),如果使用Quartz持久化存储,需保证账号能访问对应存储资源。
内容的提问来源于stack exchange,提问作者oggy oggy
相关产品推荐
相关产品推荐

