選單
GSS 技術部落格
在這個園地裡我們將從技術、專案管理、客戶對談面和大家分享我們多年的經驗,希望大家不管是喜歡或是有意見,都可以回饋給我們,讓我們有機會和大家對話並一起成長!
若有任何問題請來信:gss_crm@gss.com.tw
3 分鐘閱讀時間 (692 個字)

AspNetBoilerplate(ABP) - Background Job 介紹

abp-logo-long

 前言

在執行需要花費較久時間的工作時,如果不希望使用者等待,通常會告訴使用者這項任務正在進行中,等到執行完畢會透過 email 之類的方法通知使用者

這個時候我們就會需要用到 background job 來讓這個任務在 background threads 上執行

 作法

 建立 job

在 abp 中,建立 background job 的方法為繼承 BackgroundJob<TArgs>AsyncBackgroundJob<TArgs> 類別,或是可以直接實作 IBackgroundJob<TArgs> 介面

下面實作一個最簡單的同步 background job,模擬要寄送 email 的情況

public class SendEmailJob : BackgroundJob<User>, ITransientDependency
{
    public override void Execute(User user)
    {
        Console.WriteLine($"Welcome user {user.Name} join to this platform");
    }
} 

與一個非同步的 background job

public class SendEmailJobAsync : AsyncBackgroundJob<User>, ITransientDependency
{
    public override async Task ExecuteAsync(User user)
    {
        Console.WriteLine($"Welcome user {user.Name} join to this platform");
    }
} 

一個 background job 會定義一個 Execute 或是 ExecuteAsync 的方法,並且可以傳入參數,

background job 必須在 DI 中註冊,最簡單的辦法是實作 ITransientDependency 介面

 在 queue 中加入一個新的 job

在定義完 job 後,我們可以透過 inject IBackgroundJobManager 來新增 job 到 queue 中

public class UserAppService
{
    private readonly IBackgroundJobManager _backgroundJobManager;

    public UserAppService(IBackgroundJobManager backgroundJobManager)
    {
        _backgroundJobManager = backgroundJobManager;
    }

		public override async Task<UserDto> CreateAsync(CreateUserDto input)
    {
				var user = ObjectMapper.Map<User>(input);
				// ... 略
				_backgroundJobManager.Enqueue<SendEmailJob, User>(user);
    }
} 

我們傳入 user 給這個 job,backgroundJobManager 就會自動執行這個 job 並使用 user 當作參數來寄出 email

 實際測試一下

1. 在 UI 新增一個 user

2. 就可以在 console 看到執行 job 所印出的訊息

 預設的 Background Job Manager

IBackgroundJobManager 實作的是 BackgroundJobManager 這個 class

  • 預設的 background job manager 是一個簡單的 queue,裡面放著所有待執行的 job,並且根據先進先出的模式執行
  • 如果執行 job 的過程中發生錯誤,會一直重複執行直到 timeout,預設的 timeout 時間為 2 天
  • 在 retry 的過程中每重試一次,重是的間隔就會增加,例如第一次重試要隔 1 分鐘,第二次 2 分鐘,第三次 4 分鐘以此類推
  • 需要定義 background job store 來儲存所有的 job,如果沒有定義的話預設會將所有 job 存放在 memory 中,但如果使用第三方的 job manager(像是 hangfire)就不需要定義 store

 使用 hangfire 來替代預設的 Background Job Manager

1. 安裝 hangfire

Install-Package Abp.HangFire.AspNetCore
Install-Package Hangfire.SqlServer // 這個就看你的 hangfire 要用什麼 storage 

2. 在 startup 中註冊 handfire

services.AddHangfire(config =>
{
    config.UseSqlServerStorage(_appConfiguration.GetConnectionString("Default"));
}); 

 3. 在 configure 方法中加入 UseHangfireServer

app.UseHangfireServer(); 

4. 最後,將 abp 預設的 background job manager 替換成 hangfire,這邊就根據你是用什麼專案模板,我是用前後端分離的,所以要替換的檔案就在 [ProjectName].Web.Core 專案中的 [ProjectName]WebCoreModule.cs 這隻檔案中

[DependsOn(
		...略
+   typeof(AbpHangfireAspNetCoreModule)
)]
public class BackgroundJobWebCoreModule : AbpModule
{
		...略
		public override void PreInitialize()
    {
        // hang fire
+       Configuration.BackgroundJobs.UseHangfire();		
				... 略
		}
} 

 來看看 hangfire 版的效果

1. 在 UI 新增一個 user

2. 到 hangfire dashboard 中可以看到 job 被執行完畢

3. console 中也有印出值

 參考資料

ASP.NET Session
使用 acme.sh 幫個人網站取得免費的 SSL 憑證

相關文章

 

評論

尚無評論
已經注冊了? 這裡登入
Guest
2025/06/11, 週三

Captcha 圖像