基于 .NET 开源、功能齐全的分布式作业调度系统
最新推荐文章于 2026-08-04 14:09:15 发布
bashdotnet new console -n HangfireDemocd HangfireDemodotnet add package Hangfiredotnet add package Hangfire.Sqlite## 代码示例一:单次延迟作业与周期作业以下代码演示如何注册一个简单的延迟作业(10 秒后执行)和一个 Cron 作业(每分钟执行一次)。csharpusing Hangfire;using Hangfire.Sqlite;// 1. 配置 Hangfire 使用 SQLite 持久化存储GlobalConfiguration.Configuration.UseSqliteStorage("Data Source=hangfire.db");// 2. 启动 Hangfire 服务器(后台处理作业)using (var server = new BackgroundJobServer()){ Console.WriteLine("Hangfire 服务器已启动..."); // 3. 注册一个延迟作业:10 秒后执行 string jobId = BackgroundJob.Schedule( () => Console.WriteLine($"延迟作业执行时间:{DateTime.Now}"), TimeSpan.FromSeconds(10) ); Console.WriteLine($"延迟作业已注册,JobId: {jobId}"); // 4. 注册一个 Cron 作业:每分钟执行一次 RecurringJob.AddOrUpdate( "每分钟任务", () => Console.WriteLine($"周期性作业执行时间:{DateTime.Now}"), Cron.Minutely() // 相当于 "* * * * *" ); Console.WriteLine("周期性作业已注册(每分钟执行)"); // 保持进程运行 Console.ReadLine();}原理分析:- BackgroundJob.Schedule 将作业信息序列化并写入 SQLite 的 Job 表,State 初始为 Scheduled,ExpireAt 设置为当前时间 + 10秒。- BackgroundJobServer 的后台线程每 5 秒扫描一次 Job 表,查找 State = 'Scheduled' 且 ExpireAt <= 当前时间 的作业,将其状态改为 Enqueued 并执行。- RecurringJob.AddOrUpdate 在 RecurringJob 表中注册 Cron 表达式,服务器会定期检查该表,若满足触发条件则创建新的作业实例。## 高级特性:作业链与异常重试分布式系统中,任务可能因网络抖动或资源竞争而失败。Hangfire 提供内建的重试机制,并支持作业链(即前一个作业完成后触发下一个作业)。以下示例演示如何创建链式作业,并观察失败重试行为。csharpusing Hangfire;using Hangfire.Sqlite;GlobalConfiguration.Configuration.UseSqliteStorage("Data Source=hangfire.db");using (var server = new BackgroundJobServer()){ Console.WriteLine("服务器已启动,演示链式作业..."); // 1. 第一步:立即执行一个作业,并故意让它失败 var parentJobId = BackgroundJob.Enqueue(() => { Console.WriteLine("第一步作业开始..."); // 故意抛异常模拟失败 throw new InvalidOperationException("模拟失败"); }); // 2. 第二步:等第一步完成后执行(无论成功或失败,通过 OnAnyFinished 方式) BackgroundJob.ContinueJobWith(parentJobId, () => { Console.WriteLine("第二步作业执行(链式触发)"); }); // 3. 查看重试行为:Hangfire 默认自动重试 10 次,间隔逐渐增大 Console.WriteLine("观察控制台输出,第一步失败后会自动重试..."); Console.ReadLine();}关键机制:- ContinueJobWith 在 Job 表中创建一个新作业,其 ParentJobId 指向第一步作业。后台线程会定期检查父作业是否完成,若完成则触发子作业。- 当第一步失败时,Hangfire 自动将其状态置为 Failed,并在 StateHistory 中记录错误。然后系统根据 AutomaticRetryAttribute 决定是否重试(默认重试 10 次)。重试时,作业的 ExpireAt 会被重新计算(如首次重试延迟 5 秒,第二次 10 秒,直至指数退避)。- 若重试次数耗尽仍失败,作业最终进入 Failed 状态,可在 Dashboard 中手动重新排队。## 监控与控制:Hangfire DashboardHangfire 提供内置的 Web Dashboard,方便运维人员查看作业状态、重试、删除等。只需在 ASP.NET Core 应用中添加中间件即可。csharp// 在 Startup.cs 或 Program.cs 中app.UseHangfireDashboard(); // 默认路径 /hangfireDashboard 实时显示:- 成功/失败/在队列中的作业数量- 每个作业的执行历史(耗时、异常)- 手动触发重试或删除作业## 总结本文深入剖析了基于 .NET 的分布式作业调度系统 Hangfire 的核心原理:持久化存储、数据库锁协调、Cron 触发与自动重试。通过两个可运行代码示例,我们演示了延迟作业、周期性作业、链式作业以及失败重试机制。Hangfire 不仅功能齐全(支持 Redis、SQL Server 等后端,内置重试、Dashboard),而且开源、社区活跃,非常适合中小型到大型 .NET 项目的后台任务调度需求。关键收获:1. 分布式调度依赖持久化存储而非内存,确保可靠性。2. 作业链和重试机制降低了业务代码的复杂度。3. 通过 Dashboard 可零成本实现运维监控。无论是定时发送邮件、异步数据处理,还是复杂的 ETL 流程,Hangfire 都提供了一套优雅的解决方案。
234
222
252

被折叠的 条评论
为什么被折叠?