翻译|行业资讯|编辑:胡涛|2023-09-15 11:01:18.890|阅读 35 次
概述:本文演示ASP.NET Core 中使用 Hangfire,欢迎查阅~
# 慧都年终大促·界面/图表报表/文档/IDE等千款热门软控件火热促销中 >>
本文演示如何使用 HangFire,这是一个流行的开源库,用于 .NET Core 应用程序中的后台处理。本文构建了一个简单的应用程序,该应用程序执行一些后台处理,以演示使用 PostgreSql 作为数据库来存储数据和 dotConnect for PostgreSQL 作为 PostgreSQL 的数据提供程序所涵盖的概念。
为了从数据库中存储和检索数据,我们将使用dotConnect for PostgreSQL,这是一个构建在 ADO.NET 之上的高性能增强型 PostgreSQL 数据提供程序,可以在连接和断开连接模式下工作。
您将需要以下工具来处理代码示例:
在本文中,我们将构建一个简单的应用程序,该应用程序将演示如何在 ASP.NET 6 中自定义 HTTP 400 和 404 错误响应。以下是我们在本文中将遵循的步骤来完成此操作:
在当今的应用程序中,某些操作(例如发送电子邮件、创建报告或上传大文件)可能需要很长时间才能完成。如果您的应用程序在请求-响应周期内同步执行这些操作,则可能会导致超时和延迟。这就是后台任务可以提供帮助的地方。
后台任务是在后台执行操作的任务,这样应用程序的工作流程就不会被中断,最重要的是,当前正在执行的线程不会被阻塞。换句话说,后台任务允许您将耗时或非关键操作与应用程序的主要逻辑分开。
后台任务通常异步运行,用于从应用程序的实际请求响应周期中卸载耗时或资源密集型进程,从而允许它们在后台运行。通过将后台任务与即时用户交互分离,后台任务允许您发送电子邮件、修改数据或对警报进行排队,而无需立即用户响应。
您可以将后台作业配置为定期触发。这对于自动化正常流程(例如备份、同步和生成每日报告)非常有用。您可以专注于核心功能,并将某些后台任务卸载到其他组件,从而提高代码的可维护性。
Hangfire是一个开源库,用于处理.NET和ASP.NET Core应用程序中的后台任务。它提供了一种简单有效的方法,用于在正常的请求-响应周期之外执行长时间、耗时或重复的任务。
通过提供统一且易于使用的API,Hangfire简化了任务后台处理的实现。它无需编写复杂的线程代码或手动管理后台处理基础设施。由于其直观的 API 和丰富的功能,Hangfire 在管理 NET 应用程序中的辅助任务方面受到了开发人员的欢迎。
以下是 Hangfire 的主要特点:
Hangfire 使用三个主要组件来管理作业。其中包括存储、客户端和服务器。存储组件负责存储作业信息。客户端组件用于创建后台作业并根据配置的存储提供程序将作业存储在数据存储中。服务器组件负责执行所有后台作业。
在本部分中,我们将学习如何在 Visual Studio 2022 中创建新的 ASP.NET 6 Core Web API 项目。
现在,请按照下列步骤操作:
我们将在本文中使用该项目。
在此示例中,我们将研究如何在 ASP.NET Core 中使用 Hangfire 实现自动资源监视器。该应用程序以预定义的时间间隔在后台创建并运行重复任务,然后检索 CPU 和内存使用信息并将其存储在 PostgreSQL 数据库表中。
您可以使用 pgadmin 工具创建数据库。要使用此启动此工具创建数据库,请按照以下步骤操作:
现在按照下面给出的步骤在刚刚创建的数据库中创建一个表:
下面给出表格脚本供您参考:
CREATE TABLE perfdata ( id serial PRIMARY KEY, job_Id VARCHAR ( 255 ) NOT NULL, cpu_usage VARCHAR ( 255 ) NOT NULL, memory_usage VARCHAR ( 255 ) NOT NULL );
我们将在本文的后续部分中使用此表来演示如何使用 dotConnect for PostgreSQL 在 ASP.NET Core 中进行集成测试。
接下来,您应该将所需的 NuGet 包安装到您的项目中。您可以从 Visual Studio 内的 NuGet 包管理器工具安装它们,也可以使用以下命令从 NuGet 包管理器控制台安装它们:
PM> Install-Package Devart.Data.PostgreSql PM> Install-Package Hangfire PM> Install-Package Hangfire.MemoryStorage
dotConnect for PostgreSQL 是基于 ADO.NET 技术构建的 PostgreSQL 高性能数据提供程序,为构建基于 PostgreSQL 的数据库应用程序提供了全面的解决方案。
将 Hangfire 安装到您的项目中后,下一步就是对其进行配置。您可以使用以下代码将 Hangfire 服务添加到服务集合中:
builder.Services.AddHangfire(c => c.UseMemoryStorage()); builder.Services.AddHangfireServer();
您可以在仪表板中查看与正在运行或已完成的作业相关的实时数据。您可以通过下面给出的代码片段来开启此功能:
app.UseHangfireDashboard();
在本节中,我们将研究如何在 Hangfire 中创建作业以在后台执行处理,同时我们的应用程序继续响应。
Hangfire 为以下作业类型提供支持:
您可以使用BackgroundJob.Enqueue 方法在Hangfire 中创建后台作业。即发即忘作业是指仅被触发或执行一次的作业。创建一个名为 CustomJobController 的新 API 控制器,并在其中写入以下代码:
[Route("api/[controller]")] [ApiController] public class CustomJobController : ControllerBase { private readonly ILogger _logger; private readonly IBackgroundJobClient _backgroundJobClient; public CustomJobController(ILogger<CustomJobController> logger, IBackgroundJobClient backgroundJobClient) { _logger = logger; _backgroundJobClient = backgroundJobClient; } [HttpGet] public IActionResult Get() { var jobId = _backgroundJobClient.Enqueue(() => FireAndForgetJob(null)); Thread.Sleep(5000); return Ok($"Job Id: {jobId} completed..."); } public Task FireAndForgetJob(PerformContext context) { var jobId = context.BackgroundJob.Id; _logger.LogInformation($"Executing Job Id: {jobId}..."); return Task.CompletedTask; } }
当您执行应用程序并点击 CustomJobController 的 HttpGet 端点时,您可以看到即发即弃作业执行一次,如图 1 所示:
以下代码片段展示了如何在 Hangfire 中创建延迟作业:
var jobId = BackgroundJob.Schedule(() => Console.WriteLine("This is an example of a delayed job"), TimeSpan.FromDays(1));
在 Hangfire 中,连续作业是指父作业执行完成后立即运行的作业。您还可以在 Hangfire 中创建和管理延续任务或作业。以下代码片段显示了如何在 Hangfire 中创建延续任务:
var id = BackgroundJob.Enqueue(() => InitializeInputData()); BackgroundJob.ContinueWith(id, () => ValidateInputData());
重复性作业是根据计划执行的作业。例如,您可以有一个每周每分钟、每小时或每小时执行一次的重复作业。要在 Hangfire 中处理重复作业,您应该使用 IRecurringJobManager 接口。实际上,您应该在 CustomJobController 类的构造函数中注入 IRecurringJobManager 接口类型的实例,如下面给出的代码清单所示:
[Route("api/[controller]")] [ApiController] public class CustomJobController : ControllerBase { private readonly ILogger _logger; private readonly IRecurringJobManager _recurringJobManager; public CustomJobController(ILogger<CustomJobController> logger, IRecurringJobManager recurringJobManager) { _logger = logger; _recurringJobManager = recurringJobManager; } [HttpGet] public IActionResult Get() { var jobId = Guid.NewGuid().ToString(); _recurringJobManager.AddOrUpdate(jobId, () => CustomRecurringJob(jobId), Cron.Minutely); Thread.Sleep(5000); return Ok($"Job Id: {jobId} completed..."); } public Task CustomRecurringJob(string jobId) { _logger.LogInformation($"Executing Job Id: {jobId} at {DateTime.Now}"); return Task.CompletedTask; } }
当您执行应用程序并访问 HttpGet 端点时,您可以看到作业每分钟执行一次,如图 2 所示:
现在让我们在 Hangfire 中创建一个重复作业并使用它来检索 CPU 和内存使用数据。以下代码应该如何获取计算机上的资源使用信息:
private dynamic GetResourceUsageForProcess() { string currentProcessName = Process.GetCurrentProcess().ProcessName; PerformanceCounter cpuCounter = new PerformanceCounter("Process", "% Processor Time", currentProcessName, true); PerformanceCounter memoryCounter = new PerformanceCounter("Process", "Private Bytes", currentProcessName, true); cpuCounter.NextValue(); memoryCounter.NextValue(); Task.Delay(500); dynamic result = new ExpandoObject(); result.CPU = Math.Round(cpuCounter.NextValue() / Environment.ProcessorCount, 2); result.RAM = Math.Round(memoryCounter.NextValue() / 1024 / 1024, 2); return result; }
现在资源使用信息已可用,您应该将此信息存储在数据库中。
下面给出的 StoreResourceUsageData 方法显示了如何在 PostgreSql 数据库中保存 CPU 和内存使用数据。
public void StoreResourceUsageData(string job_id, string cpu_usage, string memory_usage) { try { using ( PgSqlConnection pgSqlConnection = new PgSqlConnection ("User Id = postgres; Password = sa123#;" + "host=localhost;database=demo; license key=Specify your license key here;")) { using (PgSqlCommand cmd = new PgSqlCommand()) { cmd.CommandText = "INSERT INTO perfdata (job_id, cpu_usage, memory_usage) " + "VALUES (:job_id, :cpu_usage, :memory_usage)"; Thread.Sleep(250); cmd.Connection = pgSqlConnection; cmd.Parameters.AddWithValue("job_id", job_id); cmd.Parameters.AddWithValue("cpu_usage", cpu_usage); cmd.Parameters.AddWithValue("memory_usage", memory_usage); if (pgSqlConnection.State != System.Data.ConnectionState.Open) pgSqlConnection.Open(); var state = pgSqlConnection.State; cmd.ExecuteNonQuery(); } } } catch (Exception ex) { throw; } }
下面给出CustomJobController的完整源码,供参考:
[Route("api/[controller]")] [ApiController] public class CustomJobController: ControllerBase { private readonly ILogger _logger; private readonly IRecurringJobManager _recurringJobManager; protected static PerformanceCounter cpuCounter; protected static PerformanceCounter memoryCounter; public CustomJobController(ILogger < CustomJobController > logger, IRecurringJobManager recurringJobManager) { _logger = logger; _recurringJobManager = recurringJobManager; } [HttpGet] public IActionResult Get() { var jobId = Guid.NewGuid().ToString(); _recurringJobManager.AddOrUpdate(jobId, () => CustomRecurringJob(jobId), Cron.Minutely); Thread.Sleep(5000); return Ok($"Job Id: {jobId} completed..."); } public Task CustomRecurringJob(string job_id) { _logger.LogInformation($"Executing Job Id: {job_id} at {DateTime.Now}"); var resourceUsage = GetResourceUsageForProcess(); string cpu_usage = resourceUsage.CPU.ToString(); string memory_usage = resourceUsage.RAM.ToString(); StoreResourceUsageData(job_id, cpu_usage, memory_usage); return Task.CompletedTask; } private dynamic GetResourceUsageForProcess() { string currentProcessName = Process.GetCurrentProcess().ProcessName; PerformanceCounter cpuCounter = new PerformanceCounter ("Process", "% Processor Time", currentProcessName, true); PerformanceCounter memoryCounter = new PerformanceCounter ("Process", "Private Bytes", currentProcessName, true); cpuCounter.NextValue(); memoryCounter.NextValue(); Task.Delay(500); dynamic result = new ExpandoObject(); result.CPU = Math.Round(cpuCounter.NextValue() / Environment.ProcessorCount, 2); result.RAM = Math.Round(memoryCounter.NextValue() / 1024 / 1024, 2); return result; } public void StoreResourceUsageData(string job_id, string cpu_usage, string memory_usage) { try { using(PgSqlConnection pgSqlConnection = new PgSqlConnection ("User Id = postgres; Password = sa123#;" + "host=localhost;database=demo; license key=Your license key;")) { using(PgSqlCommand cmd = new PgSqlCommand()) { cmd.CommandText = "INSERT INTO perfdata “ + “(job_id, cpu_usage, memory_usage) " + "VALUES (:job_id, :cpu_usage, :memory_usage)"; Thread.Sleep(250); cmd.Connection = pgSqlConnection; cmd.Parameters.AddWithValue("job_id", job_id); cmd.Parameters.AddWithValue("cpu_usage", cpu_usage); cmd.Parameters.AddWithValue("memory_usage", memory_usage); if (pgSqlConnection.State != System.Data.ConnectionState.Open) pgSqlConnection.Open(); var state = pgSqlConnection.State; cmd.ExecuteNonQuery(); } } } catch (Exception ex) { throw; } } }
当您运行应用程序时,您可以看到我们之前创建的数据库表中存储的 CPU 和内存使用信息。
Hangfire 是一个优秀的库,用于将作业集成到 .NET 和 .NET Core 应用程序中。您可以使用它在特定时间、定期或基于 cron 表达式来安排您的作业。通过使用 Hangfire,您可以提高应用程序的响应能力。借助 Hangfire 和 ASP.NET Core,您可以在后台高效地完成耗时的任务,从而最大限度地提高应用程序的性能和用户体验。
数据库管理工具交流群:765665608 欢迎进群交流讨论
本站文章除注明转载外,均为本站原创或翻译。欢迎任何形式的转载,但请务必注明出处、不得修改原文相关链接,如果存在内容上的异议请邮件反馈至chenjj@cahobeh.cn