0%

[DotnetCore]排程神器-Hangfire:入門篇

前情提要

筆者在上篇已介紹Coravel短小精幹的排程利器,固定週期排程部份皆使用Coravel套件完成,然而使用者需求越來越清楚的狀況下,意識到無法滿足所以使用者需求,事情是這樣的,使用者的某些作業需要從畫面操作,並將該項作業排進排程中,且是一次性作業,例如:使用者透過介面去設定日結作業的需求,我們會由介面呼叫API,於API中設定好某個時間點去執行該「日結作業」服務。

以上述的需求,在Coravel套件是無法做到的,Coravel是有Queue的機制,不過無法設定特定時間,筆者最近是時不時看Asp.Net Core RoadMap上所列之相關技術及推薦套件,對於上面推薦的套件,都會想要來試看看,畢竟大神們整理過的,肯定有其厲害之處,剛好於Task Scheduling作業中有推薦三套相關套件,筆者已經使用過Coravel,試試看其他,廢話不多說,趕緊來介紹今天的主角HangFire吧。

筆者開發環境及語言版本使用如下:

  • Visual Studio 2019
  • .net core 3.1
  • Web API專案

內容

建立WebAPI專案

筆者這邊省略這個步驟,提供以下語法,也可以使用Visual Studio來建立專案

1
2
3
4
mkdir HangFireDemo
dotnet new webapi -n HangFireDemo.API
dotnet new sln -n HangFireDemo
dotnet sln HangFireDemo.lsn add .\HangFireDemo.Api\HangFireDemo.API.csproj

初始化及引用

使用HangFire服務,要加三個nuget套件,分別為

  • Hangfire.Core
  • Hangfire.AspNetCore
  • Hangfire.SqlServer

以上套件中,Hangfire.CoreHangfire.AspNetCore為必要套件,接著依照自己的Persistent需求,可以選擇安裝SqlServer、Redis、PostgreSQL、MongoDb及其他,筆者這邊選擇SqlServer這個選項,因此會需要多安裝一個Hangfire.SqlServer

安裝完成後於Startup做初始化的動作,筆者這邊直接使用官網的AspNetCore Applications範例程式,有包含DashBoard功能。因要使用Sql Server當作persistent媒介,因此需先建立一個空的DB,必且於appsettings中設定連線字串。

基本上不需要事先建立相關資料表,HangFire在第一次啟動時會自動建立,但必須要知道公司的資料庫政策,筆者在公司環境時,必須要事先建好資料庫,因為application無法有create table的權限,只有read/write權限,因此提醒讀者要考量一下實際執行環境

1
2
3
4
// 本機DB,資料庫名稱為HangfireTest(依照自己命名改成自己建立的DB名稱)
"ConnectionStrings": {
"HangfireConnection": "Server=.;Initial Catalog=HangfireTest;Database=HangfireTest;Trusted_Connection=True;"
}

ConfigureServices

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// Add Hangfire services.
services.AddHangfire(configuration => configuration
.SetDataCompatibilityLevel(CompatibilityLevel.Version_170)
.UseSimpleAssemblyNameTypeSerializer()
.UseRecommendedSerializerSettings()
.UseSqlServerStorage(Configuration.GetConnectionString("HangfireConnection"), new SqlServerStorageOptions {
CommandBatchMaxTimeout = TimeSpan.FromMinutes(5),
SlidingInvisibilityTimeout = TimeSpan.FromMinutes(5),
QueuePollInterval = TimeSpan.Zero,
UseRecommendedIsolationLevel = true,
UsePageLocksOnDequeue = true,
DisableGlobalLocks = true
}));

// Add the processing server as IHostedService
services.AddHangfireServer();

Configure

1
2
// 使用Dashboard功能
app.UseHangfireDashboard();

Hangfire任務介紹及實作

Hangfire的任務,可以分成以下三種類型:

  • 一次性的任務
  • 延遲性任務,設定特定時間執行
  • 週期性任務

筆者針對這三種類型使用一個Controller來示範,為了示範可以使用注入的服務,宣告一個IJobService及其方法Execute,再者宣告一個JobService(實作IJobService),實作Execute方法部份,筆者這邊以簡單的引入NLog套件並將執行過程紀錄於檔案中。

Hangfire任務實作

1
2
3
4
5
public interface IJobService {
void OneTimeExecute();
void DelayExecute();
void SchedulerExecute();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class JobService : IJobService {
private static readonly Logger _logger = LogManager.GetCurrentClassLogger();
public void OneTimeExecute() {
_logger.Info("One Time Job Execute!");
}

public void DelayExecute() {
_logger.Info("Delay Job Execute!");
}

public void SchedulerExecute() {
_logger.Info("Scheduler Job Execute!");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
using Hangfire;

[ApiController]
[Route("[controller]")]
public class HomeController : ControllerBase {

private readonly IJobService _jobService;
public HomeController(IJobService jobService) {
_jobService = jobService;
}

[HttpGet("onetime")]
public IActionResult OneTime() {
BackgroundJob.Enqueue<IJobService>(x => x.OneTimeExecute());
return Ok();
}

[HttpGet("delay")]
public IActionResult DelayJob() {
BackgroundJob.Schedule<IJobService>(x => x.DelayExecute(), TimeSpan.FromSeconds(30));
return Ok();
}

[HttpGet("scheduler")]
public IActionResult Scheduler() {
RecurringJob.AddOrUpdate<IJobService>(x => x.SchedulerExecute(), Cron.Minutely);
return Ok();
}
}

結論

跟著筆者實作,會感覺得Hangfire的厲害,提供的三種排程執行方式,已足夠應付各式各樣的需求,以這篇的範例,應該可以構建各式各樣的排程任務。

參考: