文章目錄
使用 Hangfire 來進行 Schedule Job
最近有個舊專案 (.NET Core 2.1) 需要增加功能,升級 framework 是絕對必要的,只是其中一段用來執行每天更新 cache 的背景作業引起了我的興趣,我忘記為什麼當時沒有引用其他套件 (Hangfire
,Quartz.NET
…) 來達成定期執行的目的,但持續以來運作地也滿好的,不過因為需求單純,打算趁著這個機會想要來比較幾個套件與原生做法的優劣,今天輪到 Hangfire
需求:
- 程式啟動先執行一次快取更新
- 每日 GMT +8 00:00 執行快取更新
所有工具使用筆記在此:
- 使用原生 HostedService 來進行 Schedule Job
- 使用 Hangfire 來進行 Schedule Job
- 使用 Quartz.NET 來進行 Schedule Job”
- 使用 Coravel 來進行 Schedule Job
基本環境說明
- macOS Ventura 13.4.1
- .NET SDK 6.0.400
- JetBrains Rider 2023.1.4
NuGet library
- Hangfire.Core 1.8.4
- Hangfire.AspNetCore 1.8.4
- Hangfire.InMemory 0.5.1
更新 cache 的 code:
UpdateCacheService.cs
public class UpdateCacheService { private readonly ILogger<UpdateCacheService> _logger; public UpdateCacheService(ILogger<UpdateCacheService> logger) { _logger = logger; } public Task GetAsync(CancellationToken cancellationToken) { _logger.LogInformation("Get Data for cache"); //update cache return Task.CompletedTask; } }
設定步驟
安裝套件
Hangfire.Core 1.8.4
dotnet add package Hangfire.Core --version 1.8.4
Hangfire.AspNetCore 1.8.4
dotnet add package Hangfire.AspNetCore --version 1.8.4
Hangfire.InMemory 0.5.1
dotnet add package Hangfire.InMemory --version 0.5.1
註冊 Hangfire
官方建議
builder.Services.AddHangfire(configuration => configuration .SetDataCompatibilityLevel(CompatibilityLevel.Version_180) .UseSimpleAssemblyNameTypeSerializer() .UseRecommendedSerializerSettings() .UseInMemoryStorage());//使用 memory 來儲存資料
個人最簡版本
我推測可能是我設定的情境較單純才能用下面這個設定
builder.Services.AddHangfire(configuration => configuration .UseInMemoryStorage());//使用 memory 來儲存資料
註冊 Hangfire 處理 server 為 IHostedService
預設
15秒
會執行一次 job checkbuilder.Services.AddHangfireServer();
可以透過設定調整 check interval (以下改為
1秒
)builder.Services.AddHangfireServer(options => { options.SchedulePollingInterval = TimeSpan.FromSeconds(1); });
設定每日更新快取 job
const string updateCacheId= "UpdateCache"; app.Services.GetService<IRecurringJobManager>() .AddOrUpdate(updateCacheId, ()=> app.Services.GetService<UpdateCacheService>()!.GetAsync(new CancellationToken()), "0 0 * * *", new RecurringJobOptions { TimeZone = TimeZoneInfo.FindSystemTimeZoneById("Asia/Shanghai") } );
啟動執行單次更新
方法一:使用 BackgroundJob
app.Services.GetService<IBackgroundJobClient>().Enqueue<UpdateCacheService>(a => a.GetAsync(new CancellationToken()));
方法二:手動 trigger 每日更新 job
app.Services.GetService<IRecurringJobManager>()?.Trigger(updateCacheId);
心得
對 Hangfire 一直有個既定印象:只適合處理分鐘級以上的 job,後來才知道這個因為 job check interval 的關係,仔細想想也合理,這麼簡單的需求想來也不是很難處理,怎麼會做不到XD
- 優點:可以在 Program.cs 中設定完成、設定較多彈性
- 缺點:官網文件沒有更新 miniapi 的版本、文件比較散亂需要東翻西找、nuget library 拆比較多
完整程式碼:yowko/hangfiredemo
所有工具使用筆記在此:
- 使用原生 HostedService 來進行 Schedule Job
- 使用 Hangfire 來進行 Schedule Job
- 使用 Quartz.NET 來進行 Schedule Job”
- 使用 Coravel 來進行 Schedule Job
參考資訊
文章作者 Yowko Tsai
上次更新 2023-08-07
授權合約
本部落格 (Yowko's Notes) 所有的文章內容(包含圖片),任何轉載行為,必須通知並獲本部落格作者 (Yowko Tsai) 的同意始得轉載,且轉載皆須註明出處與作者。
Yowko's Notes 由 Yowko Tsai 製作,以創用CC 姓名標示-非商業性-相同方式分享 3.0 台灣 授權條款 釋出。