如何使用ASP.NET Core 中的 Hangfire 实现作业调度-程序员宅基地

技术标签: spring  python  java  数据库  分布式  

本文详细介绍了如何在ASP.NET Core[1]应用程序中集成 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简介

7ecb8bdb89da8dc0753b6510ef9b6822.png

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

Hangfire[2]是一个简单易用的开源库,它可以轻松地在 .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 20192.在初始屏幕上选择创建一个新项目,如下所示

87836bdf4c3218cd7f87821edb0a4894.png

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

c92afc51715f9aea2e75a7d5dd4cb9cd.png

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

7ced5698a46a9c00ca6917a85cd266ad.png

)

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

ecc55e302178ddb55a18b1c147bd1867.png

)

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

70e0a28b10d73061e746d033b2819763.png

安装所需的 Hangfire NuGet 包

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

d728eeedcb75dced1aca1b6b94161edf.png

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

790be07eba1b46e15b5873cae4511370.png

在启动时配置 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 的中间件[3]添加到添加 Hangfire 仪表板 UI 所需的ASP.NET Core 中间件管道[4]。我们将在 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 屏幕。

6bd8299e4641ea84f07112c36e4ea3ce.png

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

d0ab3acf69581e00a578684358005694.png

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

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

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

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

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

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

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

Hangfire 数据库

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

c25e2443772e624f33a684f6ac882b29.png

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

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

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

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

添加具有函数 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 时,您应该在屏幕下方

df10238f683f9a298a6ddea56ec64980.png

下面我们来看看如何在 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 中的操作方法,并且应该显示以下屏幕。但是在后台,所有配置的作业类型都应该根据它们的执行模式创建和触发。

3cc6c669da648a099948a32dea294344.png

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

43d54b8eb4a1ef01493113864dd1f90f.png

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

概括

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

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

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

下载源代码

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

References

[1] ASP.NET Core: https://procodeguide.com/tag/asp-net-core-3-1/
[2] Hangfire: https://www.hangfire.io/
[3] 中间件: https://procodeguide.com/programming/aspnet-core-middleware/
[4] ASP.NET Core 中间件管道: https://procodeguide.com/programming/aspnet-core-middleware/
[5] 如何在 ASP.NET Core 中发送电子邮件的: https://procodeguide.com/programming/how-to-send-emails-in-aspnet-core/

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/farway000/article/details/121484418

智能推荐

ASP.NET中的AutoPostBack和IsPostBack以及EnableViewState三者的运用以及区别_autopostback属性与ispostback属性的区别-程序员宅基地

文章浏览阅读927次。相信大家都在开始学ASP.NET的时候都会被它里面的几个属性搞得晕头转向,本文向各位学者介绍AutoPostBack和IsPostBack以及EnableViewState三者的运用以及区别,话不多说,让咱们来看例子来说明问题1.IsPostBack新建一个网站,在页面放置一个DropDownList和一个按钮,我希望点击按钮之后添加往DropDownList之中添加一条内容//Def_autopostback属性与ispostback属性的区别

eNSP模拟器路由器无法正常启动一直显示“#”——问题解决方法_ensp启动路由器一直显示井号 win7-程序员宅基地

文章浏览阅读2.1k次。eNSP模拟器路由器无法正常启动一直显示“#”——问题解决方法_ensp启动路由器一直显示井号 win7

TEX Quotes_c++tex quotes-程序员宅基地

文章浏览阅读963次。Think: 引号转换题, 因为不知道长度,所以用getchar() 但是不明白 为什么代码 在编译器上会 报错。。。 但是 提交是AC的。。 所以思路就是,读取字符然后判断时候是 ” , 如果是的话在判断 是第几次出现(也就是判断 是左 还是 右 引号),然后 改变 输出字符。 题目虽然很长 但是是水题 。。。Problem Description TEX is a type_c++tex quotes

打印 RichTextBox_richtextbox中的图片可以打印吗-程序员宅基地

文章浏览阅读1.5k次。创建 RichTextBoxPrintCtrl 控件下面的示例介绍了如何扩展 RichTextBox 类,以及如何使用 EM_FORMATRANGE 打印 RichTextBox 控件的内容。1.在 Visual C# .NET 中,新建一个名为 RichTextBoxPrintCtrl 的类库项目。默认情况下创建 Class1.cs。2.将 Class1._richtextbox中的图片可以打印吗

【笔记】AndroidX RecyclerView添加滚动条_androidx 滚动条-程序员宅基地

文章浏览阅读662次。添加以下代码即可android:scrollbars="vertical"其他办法无效._androidx 滚动条

学习笔记_lix重启数据库命令-程序员宅基地

文章浏览阅读525次。###重新创建索引SQL> CREATE INDEX rname_idx2 ON hr.region s (region_name)3 PARALLEL 4;索引丢失时,更为快速、简单的方法是重新创建而不是尝试恢复索引###重新创建口令验证文件1. 使用OS 验证登录到数据库。2. 将REMOTE_LOGIN_PASSWORDFILE参数设置为NONE 并重新启动数据库。_lix重启数据库命令

随便推点

初学SpringCloud:建设EurekaServer集群(新建一个EurekaServer模块)_eureka如何新增server节点到集群里-程序员宅基地

文章浏览阅读154次。目录1、背景介绍2、本篇博客的目的3、新增一个7002端口的EurekaServer模块,展示一下这个模块的文件结构4、新增一个7002端口的EurekaServer模块,展示一下这个模块的POM文件5、新增一个7002端口的EurekaServer模块,展示一下这个模块的application文件6、新增一个7002端口的EurekaServer模块,展示一下这个模块的主启动类。我的上一篇博客:初学SpringCloud:建立使用90端口的微服务模块,注册到服务注册中心_eureka如何新增server节点到集群里

matlab 简单的水轮机系统的模糊pid控制仿真_matlab仿真中有模糊pid模块吗-程序员宅基地

文章浏览阅读1k次。模糊推理系统编辑器用于设计和显示模糊推理系统的一些基本信息,如推理系统的名称,输入、输出变量的个数与名称,模糊推理系统的类型、解模糊方法等。该编辑器提供一个友好的人机图形交互环境,用来设计和修改模糊推理系中各语言变量对应的隶属度函数的相关参数,如隶属度函数的形状、范围、论域大小等,系统提供的隶属度函数有三角、梯形、高斯形、钟形等,也可用户自行定义。打开模糊推理系统编辑器,在MATLAB的命令窗(command window)内键入:fuzzy 命令,弹出模糊推理系统编辑器界面,_matlab仿真中有模糊pid模块吗

JAVA五--面向对象基础_java实验5面向对象基础-程序员宅基地

文章浏览阅读117次。基本概念编程语言总共有两大类,一类以汇编语言和c语言为首的最底层的用于嵌入式编程的面向过程编程,另一类就是以JAVA、C++、Python为首的面向对象编程。面向编程和面向对象的区别有很多,优缺点也很明显。1.运行效率,面向过程的执行效率比面向对象的执行效率更高,因为他更适用于底层的硬件上,去命令计算机做事情,面向对象是基于操作系统来控制电脑进行执行的,效率慢一点,但是思想更高级。2.运用场景,软硬件编程的区别三大特征封装、继承、多态或者可以吧抽象也加上1.封装:把相关的数据封装成一个“类”_java实验5面向对象基础

http消息当中,post和get两种请求方式的区别_get有局限性吗?-程序员宅基地

文章浏览阅读2.1k次。上一周一直在看有关微信小程序,订阅号,服务号,等微信的应用,没来的及继续学习,今个学习到javaweb 的servlet ,觉得有个地方,可以大家稍微注意一下,就是消息请求当中,GET 与 POST 这两个消息请求的方式,他们的区别在哪里,平常咱们都用的啥~首先,尼玛哥在网上查阅资料,大概是有以下几点的区别:1.Post传输的数据量大,可以达到2M,而Get方法由于受到URL长度的限制_get有局限性吗?

支付风控规则_支付宝风控规则-程序员宅基地

文章浏览阅读1.3k次。二:敢死队,不管新的还是老的,让人工智能知道我们大量的数据,越多越乱越好,这样我们做什么都是对的,因为我们什么都做,但不能一下太多,要有一个比例,比如10%到30%,偶尔还得停一下,给人工智能来一个丈二和尚。这种提交就通过了,但是很快又有风控,也是重复上面的步骤,就要你提交资料了,就是一些身份证、营业执照,单号就发快递面单就行,审核也很快,还是不行就联系客服协助处理。如果你的收款码用支付宝扫码,还能正常拉起,然后付1分钱,去账单里,就有下图这个单号了,复制这个去填上就行,可以一直保留,能一直用。_支付宝风控规则

基于SpringBoot+微信小程序的失物招领小程序_微信小程序失物招领-程序员宅基地

文章浏览阅读261次。我们基于Spring Boot和微信小程序开发的失物招领小程序旨在提供一个便捷的平台,帮助用户在失去物品或找到物品时能够迅速发布或查询相关信息。随着城市化进程的加速和人口的增长,失物招领成为了一个常见的需求,但传统的失物招领方式存在着信息传递不及时、不便捷等问题。因此,我们致力于通过技术手段解决这些问题,为用户提供一个高效、安全、便捷的失物招领平台。_微信小程序失物招领

推荐文章

热门文章

相关标签