.NET Core 8 中使用 Hangfire 进行后台作业管理

发布:2024-10-15 10:18 阅读:74 点赞:0

在现代应用程序中,将耗时的任务交由后台处理是提高系统性能的常用技术。如果没有后台任务的支持,耗时操作可能会显著影响系统性能,进而导致糟糕的用户体验,因为系统响应时间会变长。

本文将详细讲解如何在 ASP.NET Core 中执行后台任务,采用的方案并非万能之法,后台任务也存在一些挑战和限制。本文将带你逐步了解如何使用非常流行的开源库 Hangfire 来创建、调度并执行后台任务。

一、背景介绍

首先,我们将通过 Visual Studio 创建一个简单的控制台应用,并安装 Hangfire 所需的依赖包。虽然我们以控制台应用为例,但你也可以在 .NET API 项目 中触发后台任务。

二、准备工作

创建一个 .NET API 项目

  1. 创建一个名为 VideoProcessor 的 .NET API 项目(可以根据实际需求自由命名)。
  2. 在项目中安装以下必要的包:
dotnet add package Hangfire.Core
dotnet add package Hangfire.AspNetCore
dotnet add package Hangfire.PostgreSql

Hangfire 的主要组成部分

  • 存储:Hangfire 将存储有关正在运行、计划或排队的任务的必要信息。
  • 客户端:负责创建任务并将其保存到存储中。
  • 服务器:服务器从存储中查询任务并执行。Hangfire 提供了在任意进程中运行服务器的能力,即使进程终止,任务也会在重启后自动重试。
  • 仪表板:提供一个直观的用户界面来监控和调试任务,非常方便。

三、Hangfire 配置

配置数据库连接

appsettings.json 文件中添加数据库连接字符串,Hangfire 将使用该数据库存储后台任务的相关信息:

"ConnectionStrings": {
  "HangfireConnection""YourDbServer"
}

注册 Hangfire 服务

Startup.cs 中,向依赖注入容器注册 Hangfire 服务,指定使用 PostgreSQL 作为存储:

services.AddHangfire(config =>
    config.UsePostgreSqlStorage(configuration.GetConnectionString("HangfireConnection"))
);

说明:这段代码通过 UsePostgreSqlStorage 方法将 Hangfire 的存储配置为使用 PostgreSQL 数据库。

启用 Hangfire 仪表板和服务器

app.UseHangfireServer();
app.UseHangfireDashboard();

说明:这两行代码启用了 Hangfire 的服务器和仪表板。仪表板提供了监控任务的功能,默认情况下,仪表板对所有人开放。

限制仪表板的访问权限

为了保护 /hangfire 仪表板,可以通过授权限制只有认证用户才能访问:

app.UseHangfireDashboard("/hangfire"new DashboardOptions
{
    Authorization = new[] { new MyAuthorizationFilter() }
});

说明Authorization 选项指定了自定义的授权策略,确保只有通过认证的用户才能访问 Hangfire 仪表板。

四、创建任务

Hangfire 支持多种任务类型,包括立即执行的任务(Fire-and-Forget)、延迟任务、定时任务以及依赖任务。下面将逐一介绍这些任务类型。

1. Fire-and-Forget 任务

Fire-and-Forget 任务是一种最常见的后台任务类型,任务一旦被加入队列,便会立即在后台执行:

BackgroundJob.Enqueue(() =>
    Console.WriteLine("Fire-and-Forget 任务已执行。"));

说明BackgroundJob.Enqueue 方法将任务加入队列后,Hangfire 会自动安排该任务立即执行。

2. 延迟任务

延迟任务允许我们将任务的执行延迟一段时间,例如在 10 秒后执行某个任务:

BackgroundJob.Schedule(
    () => Console.WriteLine("延迟任务将在 10 秒后执行。"),
    TimeSpan.FromSeconds(10)
);

说明BackgroundJob.Schedule 方法接收两个参数,第一个是要执行的任务,第二个是延迟时间。

五、高级任务调度

1. 定时任务(Recurring Jobs)

定时任务会根据设定的 CRON 表达式重复执行,例如每分钟执行一次任务:

RecurringJob.AddOrUpdate(
    "my-recurring-job",
    () => Console.WriteLine("每分钟执行一次的定时任务。"),
    Cron.Minutely()
);

说明Cron.Minutely() 是一个内置的 CRON 表达式,表示每分钟执行一次任务。

2. 依赖任务(Continuation Jobs)

依赖任务会在父任务完成后执行,这在任务之间存在依赖关系时非常有用,例如:处理完数据后再发送通知。

var parentJobId = BackgroundJob.Enqueue(() =>
    Console.WriteLine("父任务已执行。"));

BackgroundJob.ContinueWith(parentJobId, () =>
    Console.WriteLine("依赖任务在父任务之后执行。"));

说明ContinueWith 方法可以让任务按照依赖关系串联执行。

六、多线程环境中的任务管理

在多线程环境中,管理多个任务变得更加复杂。Hangfire 提供了多线程任务的并发处理功能,通过设置 Worker 线程数量来控制并发度。

var options = new BackgroundJobServerOptions
{
    WorkerCount = Environment.ProcessorCount * 5
};

app.UseHangfireServer(options);

说明WorkerCount 指定了并发执行的线程数量,该数值根据系统 CPU 核心数动态计算。

七、任务优先级管理

可以为不同的任务设置不同的优先级,Hangfire 将根据优先级队列依次处理任务:

var options = new BackgroundJobServerOptions
{
    Queues = new[] { "critical""default""low" }
};

app.UseHangfireServer(options);

说明:通过 Queues 属性,我们可以定义不同的优先级队列。任务将按以下顺序执行:

  1. 先执行 "critical" 队列中的任务。
  2. 若 "critical" 队列为空,再执行 "default" 队列中的任务。
  3. 最后执行 "low" 队列中的任务。
// 高优先级队列任务
BackgroundJob.Enqueue(() => Console.WriteLine("执行高优先级任务"), "critical");

// 默认队列任务
BackgroundJob.Enqueue(() => Console.WriteLine("执行默认优先级任务"));

// 低优先级队列任务
BackgroundJob.Enqueue(() => Console.WriteLine("执行低优先级任务"), "low");

八、任务监控与最佳实践

Hangfire 的仪表板提供了方便的任务监控功能,帮助开发者和系统管理员追踪任务状态、检查进度并处理任务执行中的错误。

仪表板功能

常见任务状态

  • Enqueued:任务已加入队列,等待执行。
  • Processing:任务正在执行中。
  • Succeeded:任务成功完成。
  • Failed:任务执行失败。
  • Deleted:任务已被删除。

最佳实践

  1. 使用特定的队列来为任务分配不同的优先级。
  2. 配置任务自动重试机制,使用 [AutomaticRetry(Attempts = 0)] 属性指定重试次数。
  3. 实现任务超时机制,防止任务长时间挂起。
  4. 记录任务执行中的错误,并在仪表板上调试。
  5. 测试任务在生产环境前的表现,确保系统资源不会被大量耗尽。

九、总结

Hangfire 是一个功能强大的库,能够轻松管理和调度后台任务。在本文中,我们探讨了 Hangfire 在 ASP.NET Core 中的应用,从基本任务类型到高级的任务调度和监控。通过结合 Hangfire 的仪表板和多线程环境,我们可以更高效地处理耗时任务,并提高应用程序的性能和用户体验。