如何使用ASP.NET Core 中的 Hangfire 实现作业调度

https://procodeguide.com/programming/hangfire-in-aspnet-core-schedule-jobs/

如何使用ASP.NET Core 中的 Hangfire 实现作业调度

本文详细介绍了如何在ASP.NET Core应用程序中集成 Hangfire,这是一种在 .NET Core 和基于 .NET 的应用程序中调度后台作业的一种比较简单的方法。后台作业或任务允许程序员在不同的线程上执行代码,但调度和监控后台作业是一项难以实现的任务。Hangfire 简化了在 ASP.NET Core 中处理后台作业的任务。

目录

为什么或何时在 .NET Core 中安排后台作业?

Hangfire简介

Hangfire 的后台 Job 类型

​ 即发即忘

​ 延迟执行

​ 任务延续执行

Hangfire Pro 的其他工作类型

​ 批处理作业

​ 延续在 ASP.NET Core 中实现

​ Hangfire 即在 .NET Core 中安排后台作业

创建一个新的 ASP.NET Core WebAPI 项目

​ 安装所需的 Hangfire NuGet 包

​ 在启动时配置 Hangfire

​ 添加 Hangfire 仪表板I

​ Hangfire 数据库在 ASP.NET Core 中使用

​ Hangfire 创建作业

​ 即发即忘的工作

​ 延迟工作

​ 经常性工作

​ 继续工作

​ 让我们运行代码并检查结果

概括

下载源代码

为什么或何时在 .NET Core 中安排后台作业?

可能有一些 Web 请求需要花费大量时间来执行,例如生成成功插入的报告或发送电子邮件/短信作为交易完成的确认。这些请求可能需要未知的时间才能完成,并且让用户在这段时间内查看等待指示器并不能很好地处理请求。

想法是尽快为需要很长时间才能完成的请求解锁用户屏幕,以便用户能够执行其他任务。尽管用户在长时间运行的活动完成之前已被解锁,但这些活动的完成也很重要,因为它们是请求业务逻辑的一部分。

这是后台作业进入画面的地方,就像在后台运行其余活动一样,就像在不同的线程上一样,以便主线程已被释放以供用户执行其他活动。

Hangfire简介

我们在我们的应用程序中看到了后台作业的使用,但如果我们必须为后台作业创建和监控构建一个框架,那么这将是一项复杂的任务,可能需要付出很多努力。此外,这是一个设计特性,而不是一个功能特性,所以在这上面花费太多时间不会让所有利益相关者都满意。这是可以使用 Hangfire 的地方。

Hangfire是一个简单易用的开源库,它可以轻松地在 .NET Core 和 .NET 应用程序中实现后台作业。ASP.NET Core 中的 Hangfire 允许创建后台作业,甚至提供监控功能。

ASP.NET Core 中的 Hangfire 甚至支持持久存储,如 Microsoft SQL Server、Redis(作为Hangfire Pro 的一部分)等,用于存储作业信息,防止应用程序在池重新启动时丢失作业信息。存储作业信息可确保作业按照定义的类型执行,并且如果在作业执行期间发生任何异常,也会重试作业。

Hangfire 支持所有主要的日志框架,并将完整的作业执行信息记录到为应用程序配置的日志记录目的地。

Hangfire 通过确保作业根据其调度标准至少执行一次来提供后台作业的可靠性

ASP.NET Core 应用程序中的 Hangfire 可以是简单的或分布式的,即创建作业的服务器/应用程序可以与执行作业的服务器/应用程序分开。这是可能的,因为作业信息存储在可以在不同服务器/应用程序之间共享的数据库中。

Hangfire 的后台 Job 类型

使用 ASP.NET Core 中的 Hangfire,您可以创建以下类型的后台作业

即发即忘(Fire and Forget )

顾名思义,Fir and Forget 作业只执行一次,并且在创建后立即执行。这些主要用于释放主线程,使用户体验更加灵敏。

延迟

顾名思义,这些作业是在一些延迟后执行的。此延迟,即等待时间是可配置的,并在创建时排队。执行类似于用后即停。这可用于可以在峰值负载窗口之外运行的作业。

多次执行

这些是计划作业,通常在每个定义的时间间隔内执行多次。可以配置这些作业的频率,从几毫秒到几年不等。这些可以是每天或每周生成数据转储或报告的作业。

延续

Continuation 允许您定义一个工作流,即您可以配置多个(父延续作业)后台作业,这些后台作业可以根据父作业的完成情况链接在一起。即第二个作业应该执行,前提是第一个/父作业已正确执行。

Hangfire Pro 的其他工作类型

批处理作业

可以将多个后台作业链接在一起以形成批处理作业,以便它们同时一起执行。

批量延续

当父批次的作业完成时,即启动批处理中的所有作业,然后继续后台作业将启动,链接继续作业将启动。

在 ASP.NET Core 中实现 Hangfire 即在 .NET Core 中安排后台作业

创建一个新的 ASP.NET Core WebAPI 项目

为了在 ASP.NET Core 中实现 Hangfire,让我们创建一个新的 ASP.NET Core Web API 项目,在其中实现 Hangfire。

我将使用 Visual Studio 2019 社区版和 .NET Core 5 创建一个新的 Web API 项目

  1. 启动 Visual Studio 2019
  2. 在初始屏幕上选择创建一个新项目,如下所示

  1. 接下来从显示的项目类型模板列表中选择 ASP.NET Core Web Application 并单击 Next 按钮,如下面的屏幕截图所示

  1. 然后输入项目\解决方案的名称ProCodeGuide.Samples.Hangfire,提供项目将保存在本地磁盘上的路径并单击创建按钮,如下所示

)

\5. 最后选择 .NET Core Framework 为 ASP.NET Core 5.0,应用程序类型为 ASP.NET Core Web API,启用 OpenAPI Support 以进行测试并点击 Create 按钮,如下所示

)

这将创建项目并在 Visual Studio 2019 中加载相同的项目,如下图所示

安装所需的 Hangfire NuGet 包

您将需要安装 NuGet 包 Hangfire,如下所示,以将 Hangfire 引用包含到您的应用程序中。

ASP.NET Core 中的 Hangfire 包依赖于其他三个与 Hangfire NuGet 包一起安装的引用,如下所示

在启动时配置 Hangfire

既然已经安装了 Hangfire 所需的所有 NuGet 包,我们将不会在 Startup.cs 文件中配置 Hangfire。

我们将在类 Startup 的 ConfigureServices 方法中的 IServiceCollection 上添加对扩展方法 AddHangfire 和 AddHangfireServer 的调用。

public void ConfigureServices(IServiceCollection 服务)
{
    services.AddHangfire(x => x.UseSqlServerStorage("Server=(localdb)\\mssqllocaldb;Database=ProCodeGuide.Samples.Hangfire;Trusted_Connection=True;MultipleActiveResultSets=true"));
    services.AddHangfireServer();

    //为便于阅读,已删除剩余代码
}

AddHangfire – 这会将 ASP.NET Core 中的 Hangfire 添加到依赖项注入容器中,并采用 Action 委托,我们使用它设置了 SQL Server 数据库的连接字符串,以使用 SQL Server 数据库作为 Hangfire 实现的存储。

作为一个演示应用程序,我在启动类中硬编码了 SQL Server 连接字符串,但这不是一个好习惯,所以请在 appsettings.json 文件中配置您的 SQL Server 连接字符串并从那里设置它,以便您拥有特定于环境的 SQL Server连接字符串

AddHangfireServer - 这将 Hangfire Server 添加到依赖注入容器,用于配置和运行作业。

添加 Hangfire 仪表板 UI

现在让我们将 Hangfire 的中间件添加到添加 Hangfire 仪表板 UI 所需的ASP.NET Core 中间件管道。我们将在 IApplicationBuilder 实例上添加对扩展方法 UseHangfireDashboard 的调用。

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseSwagger();
        app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "ProCodeGuide.Samples.Hangfire v1"));
    }

    app.UseRouting();

    app.UseAuthorization();

    app.UseHangfireDashboard();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });
}

检查 Hangfire 仪表板 UI

现在我们已经在 ASP.NET Core 应用程序中集成了 Hangfire,让我们运行应用程序并检查 Hangfire 的仪表板。

从 Visual Studio 构建和运行应用程序后,您应该会看到以下 swagger 屏幕。

现在导航到 URL /Hangfire 后,您应该能够在 ASP.NET Core 中看到 Hangfire 的仪表板,如下所示。

从仪表板 UI,您将能够查看计划作业并监控作业状态。仪表板甚至允许您手动运行仪表板中可见的作业。仪表板上的可用信息如下

作业- 存储在数据库中的所有作业都将在此处以不同的状态显示,如已安排、已排队、正在处理、已成功、已失败、已删除和等待中。

重试- 由于先前执行期间的某些失败而重试的作业列表。

循环作业- 可以看到所有已安排为循环作业的作业列表。

服务器- 可以看到所有添加到依赖注入容器的 Hangfire 服务器。这些服务器负责处理作业。

请注意,由于仪表板 UI 会公开特定于应用程序的敏感数据,甚至允许手动执行作业,因此确保仅授权用户可以访问此仪表板非常重要。

Hangfire 在 ASP.NET Core 中默认提供的唯一安全性是它只允许对 Dashboard UI 的本地请求

Hangfire 数据库

我们确实在 ASP.NET Core 中为 Hangfire 配置了 SQL Server 数据库,作为启动时 Hangfire 配置的一部分 (AddHangfire)。当 hangfire 启动时,它会在数据库中查找所需的架构,如果该架构不存在,那么它将创建如下所示的相同

Hangfire 数据库用于存储作业信息。

在 ASP.NET Core 中使用 Hangfire 创建作业

为了在 ASP.NET Core 中演示 Hangfire 中的不同类型的作业,首先让我们创建一个虚拟服务,即 DummyEmailService,它实现了接口 IEmailService,它通过向控制台窗口写入邮件已发送而不是发送实际邮件来模拟邮件发送。

现在,如果您想实现一个使用 MailKit 库和 SMTP 服务器发送电子邮件的工作电子邮件服务,那么您可以阅读我关于如何在 ASP.NET Core 中发送电子邮件的另一篇文章

添加具有函数 SendEmail 的接口 Services/IEmailService.cs,它将在虚拟服务 DummyEmailService 中实现,以写入已发送电子邮件的控制台。

public interface IEmailService
{
    void SendEmail(string backGroundJobType, string startTime);
}

添加将实现接口 IEmailService 的类 Services/DummyEmailService 并将包含 SendEmail 方法的实现以写入控制台窗口。

public DummyEmailService : IDummyEmailService
{
    public void SendEmail(string backGroundJobType, string startTime)
    {
        Console.WriteLine(backGroundJobType + " - " + startTime + " - Email Sent - " + DateTime.Now.ToLongTimeString());
    }
}

现在在应用程序依赖注入容器中注册此服务,以便将其注入控制器。要将 DummyEmailService 添加到容器中,请在 Startup.cs 文件的方法 ConfigureServices 中添加以下代码行

services.AddTransient<IEmailService, DummyEmailService>();

现在让我们添加一个新的 API 控制器,即 EmailController,我们将注入 IEmailService 以从控制器操作方法 SendEmail 中的服务调用方法 SendEmail。

[Route("[controller]")]
[ApiController]
public class EmailController : ControllerBase
{
    private IEmailService _emailService = null;
    public EmailController(IEmailService emailService)
    {
        _emailService = emailService;
    }

    [HttpGet]
    public string SendMail()
    {
        _emailService.SendEmail("Direct Call", DateTime.Now.ToLongTimeString());
        return "Email Initiated";
    }
}

现在运行应用程序,当您导航到 URL /Email 时,您应该在屏幕下方

下面我们来看看如何在 ASP.NET Core 中实现 Hangfire 中的每一种作业

即发即忘的工作

Hangfire.BackgroundJob.Enqueue 用于创建 Fire-and-Forget 后台任务。这些作业在创建后几乎立即执行,并且只执行一次。

BackgroundJob.Enqueue(() => _emailService.SendEmail("Fire-and-Forget Job", DateTime.Now.ToLongTimeString()));

延迟工作

Hangfire.BackgroundJob.Schedule 用于创建 Delayed 后台任务。这些作业是延迟创建的,并在配置的延迟时间过后执行。

BackgroundJob.Schedule(() => _emailService.SendEmail("Delayed Job",DateTime.Now.ToLongTimeString()),TimeSpan.FromSeconds(30));

经常性工作

Hangfire.RecurringJob.AddOrUpdate 用于创建循环后台任务。这些可以是按照定义的频率执行的每分钟、每天或每周的工作。

RecurringJob.AddOrUpdate(() => _emailService.SendEmail("Recurring Job", DateTime.Now.ToLongTimeString()),Cron.Minutely);

继续工作

Hangfire.BackgroundJob.ContinueJobWith 用于创建延续后台任务。这些作业会在链接的先前作业成功执行后立即执行。

var jobId = BackgroundJob.Schedule(() => _emailService.SendEmail("Continuation Job 1", DateTime.Now.ToLongTimeString()), TimeSpan.FromSeconds(45));BackgroundJob.ContinueJobWith(jobId, () => Console.WriteLine("Continuation Job 2 - Email Reminder - " + DateTime.Now.ToLongTimeString()));

最后,我修改了 EmailController 中 SendMail 操作方法中的代码,如下所示,以演示 ASP.NET Core 中 Hangfire 中可用的每种类型的后台作业的执行模式

[HttpGet]public string SendMail(){    _emailService.SendEmail("Direct Call", DateTime.Now.ToLongTimeString());    BackgroundJob.Enqueue(() => _emailService.SendEmail("Fire-and-Forget Job", DateTime.Now.ToLongTimeString()));    BackgroundJob.Schedule(() => _emailService.SendEmail("Delayed Job", DateTime.Now.ToLongTimeString()),TimeSpan.FromSeconds(30));    RecurringJob.AddOrUpdate(() => _emailService.SendEmail("Recurring Job", DateTime.Now.ToLongTimeString()),Cron.Minutely);    var jobId = BackgroundJob.Schedule(() => _emailService.SendEmail("Continuation Job 1", DateTime.Now.ToLongTimeString()), TimeSpan.FromSeconds(45));    BackgroundJob.ContinueJobWith(jobId, () => Console.WriteLine("Continuation Job 2 - Email Reminder - " + DateTime.Now.ToLongTimeString()));    return "Email Initiated";}

让我们运行代码并检查结果

现在让我们运行代码来检查 ASP.NET Core 中 Hangfire 中可用的不同类型作业的执行模式。

运行应用程序后导航到 URL /Email 这应该调用 SendEmail 以获取 EmailController 中的操作方法,并且应该显示以下屏幕。但是在后台,所有配置的作业类型都应该根据它们的执行模式创建和触发。

让我们查看控制台窗口中的 ASP.NET Core 中 Hangfire 中不同类型的作业是否已被触发

我们可以从上面的屏幕中看到,所有作业都是按照它们的执行模式触发的。

概括

在本文中,我们将了解后台作业、ASP.NET Core 中的 Hangfire 以及 ASP.NET Core 中 Hangfire 中可用的不同类型作业的实现。

我们还看到,甚至还有一个付费版本的 Hangfire,即Hangfire Pro,它支持 Redis 作为数据库,还支持一些额外的复杂作业类型,如批处理和批处理延续。

我希望你喜欢这篇文章,在下面的评论部分让我知道你的反馈

下载源代码

在 ASP.NET Core 中实现 Hangfire 的源代码下载链接https://github.com/procodeguide/ProCodeGuide.Samples.Hangfire

posted @ 2021-11-20 23:03  溪源More  阅读(1687)  评论(0编辑  收藏  举报