Quartz.NET是一个功能齐全的开源作业调用系统,大大小小的应用程序都可使用。
创建一个asp.NET core web项目,使用quartz.NET的作业,定时调用远程接口是否能正常访问,发生异常调用飞书消息接口,把异常发送给指定的同事飞书。
1.准备工作
定义一个作业调用的服务接口ICheckService
代码语言:javascript复制 public interface ICheckService
{
Task ConnectRemoteApi(ConnectRemoteApiInput input);
}
实现类CheckService
代码语言:javascript复制public class CheckService : ICheckService
{
private readonly ILogger<CheckService> _logger;
private readonly IHttpClientFactory _httpClientFactory;
private readonly AppSetting _appSetting;
public CheckService(ILogger<CheckService> logger, IHttpClientFactory httpClientFactory
, IOptionsMonitor<AppSetting> options)
{
_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)
{
//通过飞书发送消息给指定的人员
_logger.LogInformation(ex.Message);
}
}
}
实现Ijob接口
代码语言:javascript复制public class CheckRemoteApiJob : IJob
{
private readonly ICheckService _checkService;
private readonly AppSetting _appSetting;
public CheckRemoteApiJob(ICheckService checkService, IOptionsMonitor<AppSetting> options)
{
_checkService = checkService;
_appSetting = options.CurrentValue;
}
public async Task Execute(IJobExecutionContext context)
{
await _checkService.ConnectRemoteApi(new ConnectRemoteApiInput
{
InnerCode = _appSetting.InnerCode,
});
}
}
请先安装Quartz.AspNetCore nuget包,我使用的是最新的版本3.4.0,Execute方法默认是异步的,如果你的业务没有异步,可以使用Task.CompletedTask。
2.Job和Trigger绑定
作业已经实现,何时进行触发呢,Quartz.NET提供了一个trigger的概念。job和trigger进行绑定,Quartz既可以调度我们的job了。触发器和job的绑定,可以通过代码的方式,也可以通过xml形式(可以通过设置参数ScanInterval支持定期去扫描最新的变动),以下代码演示代码配置的两种方式进行调度我们的作业CheckRemoteApiJob。
2.1.使用ScheduleJob方法,Job绑定到单个Trigger,代码如下:
代码语言:javascript复制builder.Services.Configure<AppSetting>(builder.Configuration.GetSection("AppSetting"));
builder.Services.AddHttpClient();
builder.Services.AddScoped<ICheckService, CheckService>();
builder.Services.AddQuartz(q =>
{
//支持DI,默认Ijob 实现不支持有参构造函数
q.UseMicrosoftDependencyInjectionJobFactory();
q.ScheduleJob<CheckRemoteApiJob>(trigger => trigger
.WithIdentity("ConnectionRemoteApiTrigger")
.StartAt(DateBuilder.EvenSecondDate(DateTimeOffset.UtcNow.AddSeconds(7)))
.WithDailyTimeIntervalSchedule(x => x.WithInterval(builder.Configuration.GetValue<int>("AppSetting:CheckRemoteApiJobIntervalMinute"), IntervalUnit.Minute))
.WithDescription("定时访问远程接口")
);
});
builder.Services.AddQuartzServer(options =>
{
// when shutting down we want jobs to complete gracefully
options.WaitForJobsToComplete = true;
});
builder.Services.AddTransient<CheckRemoteApiJob>();
调用ScheduleJob方法,job默认只能绑定一个trigger。
运行代码,在控制台查看,每隔1分钟输出如下
2.2.job可以绑定到多个Trigger
代码语言:javascript复制builder.Services.AddQuartz(q =>
{
//支持DI,默认Ijob 实现不支持有参构造函数
q.UseMicrosoftDependencyInjectionJobFactory();
//------sample
//q.ScheduleJob<CheckRemoteApiJob>(trigger => trigger
// .WithIdentity("ConnectionRemoteApiTrigger")
// .StartAt(DateBuilder.EvenSecondDate(DateTimeOffset.UtcNow.AddSeconds(7)))
// .WithDailyTimeIntervalSchedule(x => x.WithInterval(builder.Configuration.GetValue<int>("AppSetting:CheckRemoteApiJobIntervalMinute"), IntervalUnit.Minute))
// .WithDescription("定时访问远程接口")
// );
//---------cron
var jobKey = new JobKey("ConnectionRemoteApi job", "ConnectionRemoteApi group");
q.AddJob<CheckRemoteApiJob>(jobKey, j => {
j.WithDescription("定时访问远程接口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("定时访问远程接口trigger")
);
});
如果不想使用cron表达式,也可以使用方法 WithSimpleSchedule替换 如:
代码语言:javascript复制WithSimpleSchedule(x=> x.WithInterval(TimeSpan.FromMinutes(builder.Configuration.GetValue<int>"AppSetting:CheckRemoteApiJobIntervalMinute"))).RepeatForever())
再次运行代码,跟上面的输出是一样的。
参考官网:https://www.quartz-scheduler.net/