.NET6用起來-Quartz.NET
Quartz.NET是一個(gè)功能齊全的開源作業(yè)調(diào)用系統(tǒng),大大小小的應(yīng)用程序都可使用。
創(chuàng)建一個(gè)asp.NET core web項(xiàng)目,使用quartz.NET的作業(yè),定時(shí)調(diào)用遠(yuǎn)程接口是否能正常訪問,發(fā)生異常調(diào)用飛書消息接口,把異常發(fā)送給指定的同事飛書。
1.準(zhǔn)備工作
定義一個(gè)作業(yè)調(diào)用的服務(wù)接口ICheckService
public interface ICheckService{Task ConnectRemoteApi(ConnectRemoteApiInput input);}
實(shí)現(xiàn)類CheckService
public class CheckService : ICheckService{private readonly ILogger_logger; private readonly IHttpClientFactory _httpClientFactory;private readonly AppSetting _appSetting;public CheckService(ILoggerlogger, IHttpClientFactory httpClientFactory , IOptionsMonitoroptions) {_logger = logger;_httpClientFactory = httpClientFactory;_appSetting = options.CurrentValue;}public async Task ConnectRemoteApi(ConnectRemoteApiInput input){var para = new SecurityCodeInput(){Code = input.InnerCode,Inner = input.Inner};HttpClient client = _httpClientFactory.CreateClient();var paraContent = new StringContent(JsonSerializer.Serialize(para),encoding: Encoding.UTF8,mediaType: "application/json");try{using var httpResponse = await client.PostAsync(_appSetting.CheckUrl, paraContent);var result = await httpResponse.Content.ReadAsStringAsync();_logger.LogInformation(httpResponse.StatusCode.ToString());}catch (Exception ex){//通過飛書發(fā)送消息給指定的人員_logger.LogInformation(ex.Message);}}}
實(shí)現(xiàn)Ijob接口
public class CheckRemoteApiJob : IJob{private readonly ICheckService _checkService;private readonly AppSetting _appSetting;public CheckRemoteApiJob(ICheckService checkService, IOptionsMonitoroptions) {_checkService = checkService;_appSetting = options.CurrentValue;}public async Task Execute(IJobExecutionContext context){await _checkService.ConnectRemoteApi(new ConnectRemoteApiInput{InnerCode = _appSetting.InnerCode,});}}
請(qǐng)先安裝Quartz.AspNetCore nuget包,我使用的是最新的版本3.4.0,Execute方法默認(rèn)是異步的,如果你的業(yè)務(wù)沒有異步,可以使用Task.CompletedTask。
2.Job和Trigger綁定
作業(yè)已經(jīng)實(shí)現(xiàn),何時(shí)進(jìn)行觸發(fā)呢,Quartz.NET提供了一個(gè)trigger的概念。job和trigger進(jìn)行綁定,Quartz既可以調(diào)度我們的job了。觸發(fā)器和job的綁定,可以通過代碼的方式,也可以通過xml形式(可以通過設(shè)置參數(shù)ScanInterval支持定期去掃描最新的變動(dòng)),以下代碼演示代碼配置的兩種方式進(jìn)行調(diào)度我們的作業(yè)CheckRemoteApiJob。
2.1.使用ScheduleJob方法,Job綁定到單個(gè)Trigger,代碼如下:
builder.Services.Configure(builder.Configuration.GetSection("AppSetting")); builder.Services.AddHttpClient();builder.Services.AddScoped(); builder.Services.AddQuartz(q =>{//支持DI,默認(rèn)Ijob 實(shí)現(xiàn)不支持有參構(gòu)造函數(shù)q.UseMicrosoftDependencyInjectionJobFactory();q.ScheduleJob(trigger => trigger .WithIdentity("ConnectionRemoteApiTrigger").StartAt(DateBuilder.EvenSecondDate(DateTimeOffset.UtcNow.AddSeconds(7))).WithDailyTimeIntervalSchedule(x => x.WithInterval(builder.Configuration.GetValue("AppSetting:CheckRemoteApiJobIntervalMinute"), IntervalUnit.Minute)) .WithDescription("定時(shí)訪問遠(yuǎn)程接口"));});builder.Services.AddQuartzServer(options =>{// when shutting down we want jobs to complete gracefullyoptions.WaitForJobsToComplete = true;});builder.Services.AddTransient();
調(diào)用ScheduleJob方法,job默認(rèn)只能綁定一個(gè)trigger。
運(yùn)行代碼,在控制臺(tái)查看,每隔1分鐘輸出如下

2.2.job可以綁定到多個(gè)Trigger
builder.Services.AddQuartz(q =>{//支持DI,默認(rèn)Ijob 實(shí)現(xiàn)不支持有參構(gòu)造函數(shù)q.UseMicrosoftDependencyInjectionJobFactory();//------sample//q.ScheduleJob(trigger => trigger // .WithIdentity("ConnectionRemoteApiTrigger")// .StartAt(DateBuilder.EvenSecondDate(DateTimeOffset.UtcNow.AddSeconds(7)))// .WithDailyTimeIntervalSchedule(x => x.WithInterval(builder.Configuration.GetValue("AppSetting:CheckRemoteApiJobIntervalMinute"), IntervalUnit.Minute)) // .WithDescription("定時(shí)訪問遠(yuǎn)程接口")// );//---------cronvar jobKey = new JobKey("ConnectionRemoteApi job", "ConnectionRemoteApi group");q.AddJob(jobKey, j => { j.WithDescription("定時(shí)訪問遠(yuǎn)程接口job");});q.AddTrigger(t => t.WithIdentity("ConnectionRemoteApi Cron Trigger").ForJob(jobKey).StartAt(DateBuilder.EvenSecondDate(DateTimeOffset.UtcNow.AddSeconds(3))).WithCronSchedule(builder.Configuration.GetValue<string>("AppSetting:CheckRemoteApiJobCron")).WithDescription("定時(shí)訪問遠(yuǎn)程接口trigger"));});
如果不想使用cron表達(dá)式,也可以使用方法 WithSimpleSchedule替換 如:
WithSimpleSchedule(x=> x.WithInterval(TimeSpan.FromMinutes(builder.Configuration.GetValue"AppSetting:CheckRemoteApiJobIntervalMinute"))).RepeatForever()) 再次運(yùn)行代碼,跟上面的輸出是一樣的。
參考官網(wǎng):https://www.quartz-scheduler.net/
