翻譯|行業(yè)資訊|編輯:胡濤|2023-09-15 11:01:18.890|閱讀 122 次
概述:本文演示ASP.NET Core 中使用 Hangfire,歡迎查閱~
# 界面/圖表報表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
本文演示如何使用 HangFire,這是一個流行的開源庫,用于 .NET Core 應用程序中的后臺處理。本文構(gòu)建了一個簡單的應用程序,該應用程序執(zhí)行一些后臺處理,以演示使用 PostgreSql 作為數(shù)據(jù)庫來存儲數(shù)據(jù)和 dotConnect for PostgreSQL 作為 PostgreSQL 的數(shù)據(jù)提供程序所涵蓋的概念。
為了從數(shù)據(jù)庫中存儲和檢索數(shù)據(jù),我們將使用dotConnect for PostgreSQL,這是一個構(gòu)建在 ADO.NET 之上的高性能增強型 PostgreSQL 數(shù)據(jù)提供程序,可以在連接和斷開連接模式下工作。
您將需要以下工具來處理代碼示例:
在本文中,我們將構(gòu)建一個簡單的應用程序,該應用程序?qū)⒀菔救绾卧?ASP.NET 6 中自定義 HTTP 400 和 404 錯誤響應。以下是我們在本文中將遵循的步驟來完成此操作:
在當今的應用程序中,某些操作(例如發(fā)送電子郵件、創(chuàng)建報告或上傳大文件)可能需要很長時間才能完成。如果您的應用程序在請求-響應周期內(nèi)同步執(zhí)行這些操作,則可能會導致超時和延遲。這就是后臺任務(wù)可以提供幫助的地方。
后臺任務(wù)是在后臺執(zhí)行操作的任務(wù),這樣應用程序的工作流程就不會被中斷,最重要的是,當前正在執(zhí)行的線程不會被阻塞。換句話說,后臺任務(wù)允許您將耗時或非關(guān)鍵操作與應用程序的主要邏輯分開。
后臺任務(wù)通常異步運行,用于從應用程序的實際請求響應周期中卸載耗時或資源密集型進程,從而允許它們在后臺運行。通過將后臺任務(wù)與即時用戶交互分離,后臺任務(wù)允許您發(fā)送電子郵件、修改數(shù)據(jù)或?qū)瘓筮M行排隊,而無需立即用戶響應。
您可以將后臺作業(yè)配置為定期觸發(fā)。這對于自動化正常流程(例如備份、同步和生成每日報告)非常有用。您可以專注于核心功能,并將某些后臺任務(wù)卸載到其他組件,從而提高代碼的可維護性。
Hangfire是一個開源庫,用于處理.NET和ASP.NET Core應用程序中的后臺任務(wù)。它提供了一種簡單有效的方法,用于在正常的請求-響應周期之外執(zhí)行長時間、耗時或重復的任務(wù)。
通過提供統(tǒng)一且易于使用的API,Hangfire簡化了任務(wù)后臺處理的實現(xiàn)。它無需編寫復雜的線程代碼或手動管理后臺處理基礎(chǔ)設(shè)施。由于其直觀的 API 和豐富的功能,Hangfire 在管理 NET 應用程序中的輔助任務(wù)方面受到了開發(fā)人員的歡迎。
以下是 Hangfire 的主要特點:
Hangfire 使用三個主要組件來管理作業(yè)。其中包括存儲、客戶端和服務(wù)器。存儲組件負責存儲作業(yè)信息。客戶端組件用于創(chuàng)建后臺作業(yè)并根據(jù)配置的存儲提供程序?qū)⒆鳂I(yè)存儲在數(shù)據(jù)存儲中。服務(wù)器組件負責執(zhí)行所有后臺作業(yè)。
在本部分中,我們將學習如何在 Visual Studio 2022 中創(chuàng)建新的 ASP.NET 6 Core Web API 項目。
現(xiàn)在,請按照下列步驟操作:
我們將在本文中使用該項目。
在此示例中,我們將研究如何在 ASP.NET Core 中使用 Hangfire 實現(xiàn)自動資源監(jiān)視器。該應用程序以預定義的時間間隔在后臺創(chuàng)建并運行重復任務(wù),然后檢索 CPU 和內(nèi)存使用信息并將其存儲在 PostgreSQL 數(shù)據(jù)庫表中。
您可以使用 pgadmin 工具創(chuàng)建數(shù)據(jù)庫。要使用此啟動此工具創(chuàng)建數(shù)據(jù)庫,請按照以下步驟操作:
現(xiàn)在按照下面給出的步驟在剛剛創(chuàng)建的數(shù)據(jù)庫中創(chuàng)建一個表:
下面給出表格腳本供您參考:
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 );
我們將在本文的后續(xù)部分中使用此表來演示如何使用 dotConnect for PostgreSQL 在 ASP.NET Core 中進行集成測試。
接下來,您應該將所需的 NuGet 包安裝到您的項目中。您可以從 Visual Studio 內(nèi)的 NuGet 包管理器工具安裝它們,也可以使用以下命令從 NuGet 包管理器控制臺安裝它們:
PM> Install-Package Devart.Data.PostgreSql PM> Install-Package Hangfire PM> Install-Package Hangfire.MemoryStorage
dotConnect for PostgreSQL 是基于 ADO.NET 技術(shù)構(gòu)建的 PostgreSQL 高性能數(shù)據(jù)提供程序,為構(gòu)建基于 PostgreSQL 的數(shù)據(jù)庫應用程序提供了全面的解決方案。
將 Hangfire 安裝到您的項目中后,下一步就是對其進行配置。您可以使用以下代碼將 Hangfire 服務(wù)添加到服務(wù)集合中:
builder.Services.AddHangfire(c => c.UseMemoryStorage()); builder.Services.AddHangfireServer();
您可以在儀表板中查看與正在運行或已完成的作業(yè)相關(guān)的實時數(shù)據(jù)。您可以通過下面給出的代碼片段來開啟此功能:
app.UseHangfireDashboard();
在本節(jié)中,我們將研究如何在 Hangfire 中創(chuàng)建作業(yè)以在后臺執(zhí)行處理,同時我們的應用程序繼續(xù)響應。
Hangfire 為以下作業(yè)類型提供支持:
您可以使用BackgroundJob.Enqueue 方法在Hangfire 中創(chuàng)建后臺作業(yè)。即發(fā)即忘作業(yè)是指僅被觸發(fā)或執(zhí)行一次的作業(yè)。創(chuàng)建一個名為 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; } }
當您執(zhí)行應用程序并點擊 CustomJobController 的 HttpGet 端點時,您可以看到即發(fā)即棄作業(yè)執(zhí)行一次,如圖 1 所示:
以下代碼片段展示了如何在 Hangfire 中創(chuàng)建延遲作業(yè):
var jobId = BackgroundJob.Schedule(() => Console.WriteLine("This is an example of a delayed job"), TimeSpan.FromDays(1));
在 Hangfire 中,連續(xù)作業(yè)是指父作業(yè)執(zhí)行完成后立即運行的作業(yè)。您還可以在 Hangfire 中創(chuàng)建和管理延續(xù)任務(wù)或作業(yè)。以下代碼片段顯示了如何在 Hangfire 中創(chuàng)建延續(xù)任務(wù):
var id = BackgroundJob.Enqueue(() => InitializeInputData()); BackgroundJob.ContinueWith(id, () => ValidateInputData());
重復性作業(yè)是根據(jù)計劃執(zhí)行的作業(yè)。例如,您可以有一個每周每分鐘、每小時或每小時執(zhí)行一次的重復作業(yè)。要在 Hangfire 中處理重復作業(yè),您應該使用 IRecurringJobManager 接口。實際上,您應該在 CustomJobController 類的構(gòu)造函數(shù)中注入 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; } }
當您執(zhí)行應用程序并訪問 HttpGet 端點時,您可以看到作業(yè)每分鐘執(zhí)行一次,如圖 2 所示:
現(xiàn)在讓我們在 Hangfire 中創(chuàng)建一個重復作業(yè)并使用它來檢索 CPU 和內(nèi)存使用數(shù)據(jù)。以下代碼應該如何獲取計算機上的資源使用信息:
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; }
現(xiàn)在資源使用信息已可用,您應該將此信息存儲在數(shù)據(jù)庫中。
下面給出的 StoreResourceUsageData 方法顯示了如何在 PostgreSql 數(shù)據(jù)庫中保存 CPU 和內(nèi)存使用數(shù)據(jù)。
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; } } }
當您運行應用程序時,您可以看到我們之前創(chuàng)建的數(shù)據(jù)庫表中存儲的 CPU 和內(nèi)存使用信息。
Hangfire 是一個優(yōu)秀的庫,用于將作業(yè)集成到 .NET 和 .NET Core 應用程序中。您可以使用它在特定時間、定期或基于 cron 表達式來安排您的作業(yè)。通過使用 Hangfire,您可以提高應用程序的響應能力。借助 Hangfire 和 ASP.NET Core,您可以在后臺高效地完成耗時的任務(wù),從而最大限度地提高應用程序的性能和用戶體驗。
數(shù)據(jù)庫管理工具交流群:765665608 歡迎進群交流討論
正版數(shù)據(jù)庫管理軟件下載、購買、授權(quán)咨詢,請點這里!
本站文章除注明轉(zhuǎn)載外,均為本站原創(chuàng)或翻譯。歡迎任何形式的轉(zhuǎn)載,但請務(wù)必注明出處、不得修改原文相關(guān)鏈接,如果存在內(nèi)容上的異議請郵件反饋至chenjj@fc6vip.cn