从零配置到上线:在ASP.NET Core 6里分别集成Hangfire与Quartz.NET的保姆级教程

张开发
2026/4/6 11:08:12 15 分钟阅读

分享文章

从零配置到上线:在ASP.NET Core 6里分别集成Hangfire与Quartz.NET的保姆级教程
从零配置到上线在ASP.NET Core 6里分别集成Hangfire与Quartz.NET的保姆级教程当你第一次在ASP.NET Core项目中需要处理后台任务时面对Hangfire和Quartz.NET这两个主流库可能会感到困惑。作为过来人我完全理解这种选择困难——特别是在项目deadline临近时一个能快速上手的解决方案比理论对比更有价值。本文将带你用最短的时间以两种最实用的方式完成从零配置到生产环境部署的全过程。1. 环境准备与基础配置在开始之前确保你已经创建了一个ASP.NET Core 6项目。打开NuGet包管理器我们需要安装以下基础依赖dotnet add package Microsoft.EntityFrameworkCore.SqlServer dotnet add package Microsoft.EntityFrameworkCore.Tools对于Hangfire方案额外安装dotnet add package Hangfire.Core dotnet add package Hangfire.AspNetCore dotnet add package Hangfire.SqlServer对于Quartz.NET方案则需要dotnet add package Quartz dotnet add package Quartz.Extensions.Hosting重要提示建议在开发环境使用LocalDB作为临时存储生产环境务必配置完整的SQL Server实例。我曾经在一个紧急项目中因为忽略这点导致上线后任务丢失。2. Hangfire实战从仪表盘到异常处理2.1 数据库配置与初始化首先在appsettings.json中添加数据库连接字符串{ ConnectionStrings: { HangfireConnection: Server(localdb)\\mssqllocaldb;DatabaseHangfireDemo;Trusted_ConnectionTrue; } }然后在Program.cs中进行服务注册builder.Services.AddHangfire(config config.UseSqlServerStorage(builder.Configuration.GetConnectionString(HangfireConnection))); builder.Services.AddHangfireServer();应用启动时自动创建所需表结构dotnet ef migrations add InitialHangfireSchema dotnet ef database update2.2 实现Fire-and-forget任务创建一个简单的邮件发送服务public class EmailService { public void SendWelcomeEmail(string email) { // 模拟邮件发送 Console.WriteLine($Sending welcome email to {email} at {DateTime.Now}); } }在控制器中调用public class UserController : Controller { private readonly IBackgroundJobClient _backgroundJob; public UserController(IBackgroundJobClient backgroundJob) { _backgroundJob backgroundJob; } [HttpPost] public IActionResult Register(string email) { _backgroundJob.Enqueue(() new EmailService().SendWelcomeEmail(email)); return Ok(); } }2.3 异常处理与自动重试Hangfire默认会自动重试失败的任务但我们可以自定义重试策略[AutomaticRetry(Attempts 3, OnAttemptsExceeded AttemptsExceededAction.Delete)] public class PaymentProcessor { public void ProcessPayment(int orderId) { // 支付处理逻辑 if (new Random().Next(0, 10) 0) throw new Exception(模拟支付失败); Console.WriteLine($Order {orderId} processed successfully); } }3. Quartz.NET深度配置从Cron表达式到集群部署3.1 基础作业与触发器配置创建简单的日志作业public class LoggingJob : IJob { public Task Execute(IJobExecutionContext context) { Console.WriteLine($Job executed at {DateTime.Now}); return Task.CompletedTask; } }在Program.cs中配置builder.Services.AddQuartz(q { q.UseMicrosoftDependencyInjectionJobFactory(); var jobKey new JobKey(LoggingJob); q.AddJobLoggingJob(opts opts.WithIdentity(jobKey)); q.AddTrigger(opts opts .ForJob(jobKey) .WithIdentity(LoggingTrigger) .WithCronSchedule(0 0/5 * * * ?)); // 每5分钟执行 }); builder.Services.AddQuartzHostedService(q q.WaitForJobsToComplete true);3.2 数据库持久化配置首先在appsettings.json中添加配置{ Quartz: { jobStore.type: Quartz.Impl.AdoJobStore.JobStoreTX, Quartz, jobStore.dataSource: default, jobStore.tablePrefix: QRTZ_, dataSource.default.connectionString: Server(localdb)\\mssqllocaldb;DatabaseQuartzDemo;Trusted_ConnectionTrue;, dataSource.default.provider: SqlServer } }然后修改Quartz配置builder.Services.AddQuartz(q { q.UsePersistentStore(s { s.UseSqlServer(builder.Configuration.GetConnectionString(QuartzConnection)); s.UseJsonSerializer(); }); // ...其余配置 });3.3 实现作业监听器创建执行日志监听器public class JobListener : IJobListener { public string Name GlobalJobListener; public Task JobToBeExecuted(IJobExecutionContext context, CancellationToken cancellationToken) { Console.WriteLine($Job {context.JobDetail.Key} is about to execute); return Task.CompletedTask; } public Task JobExecutionVetoed(IJobExecutionContext context, CancellationToken cancellationToken) { return Task.CompletedTask; } public Task JobWasExecuted(IJobExecutionContext context, JobExecutionException jobException, CancellationToken cancellationToken) { Console.WriteLine($Job {context.JobDetail.Key} completed in {context.JobRunTime.TotalMilliseconds}ms); return Task.CompletedTask; } }注册监听器q.AddJobListenerJobListener();4. 生产环境优化与常见问题排查4.1 性能调优参数对比配置项Hangfire推荐值Quartz.NET推荐值工作线程数WorkerCount 20ThreadPool.Size 25队列检查间隔15秒30秒数据库轮询禁用(UsePollingfalse)misfireThreshold60s重试策略自动3次重试misfireInstructionFireOnceNow4.2 常见错误解决方案Hangfire仪表盘无法访问检查是否添加了app.UseHangfireDashboard()确认授权配置正确app.UseHangfireDashboard(/hangfire, new DashboardOptions { Authorization new[] { new HangfireAuthorizationFilter() } });Quartz.NET作业未触发检查数据库连接是否正常验证Cron表达式是否正确确保AddQuartzHostedService已注册4.3 监控与日志集成对于Hangfire可以直接使用内置仪表盘。而Quartz.NET需要自定义监控方案public class QuartzHealthCheck : IHealthCheck { private readonly ISchedulerFactory _schedulerFactory; public QuartzHealthCheck(ISchedulerFactory schedulerFactory) { _schedulerFactory schedulerFactory; } public async TaskHealthCheckResult CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken) { var scheduler await _schedulerFactory.GetScheduler(cancellationToken); return scheduler.IsStarted ? HealthCheckResult.Healthy() : HealthCheckResult.Unhealthy(); } }注册健康检查builder.Services.AddHealthChecks() .AddCheckQuartzHealthCheck(quartz);

更多文章