首页 > 其他分享 >Quartz.Net 官方教程 Best Practices

Quartz.Net 官方教程 Best Practices

时间:2023-02-01 15:36:21浏览次数:47  
标签:DateTimeOffset 触发器 Quartz 作业 Practices 2023 var 90 Net

最佳实践

JobDataMap
  1. 建议只存储基本数据(含String),避免序列化问题

  2. 作业执行期间,JobDetail和Trgger的底层共用一个JobDataMap 实例,因此Trigger的数据会覆盖Job中相同key的值。

  3. 每个独立触发器的JobDataMap 是独立的

  4. 在作业执行期间,建议使用MergedJobDataMap去检索key

    // 不建议
    var badMethod = context.JobDetail.JobDataMap.GetString("a-value");
    var alsoBadMethod = context.Trigger.JobDataMap.GetString("a-value");
    // 建议
    var goodMethod = context.MergedJobDataMap.GetString("a-value");
    
Job

​ 为统一作业的名称和群组,建议在IJob实现时就声明一个静态JobKey,便于触发器赋值使用

public class SomeJob : IJob 
{
	// 定义当前作业的名称和群组
    public static readonly JobKey Key = new JobKey("job-name", "group-name");

    public Task Execute(IJobExecutionContext context) { /* elided */ }
}
// 创建触发器
public async Task DoSomething(IScheduler schedule, CancellationToken ct)
{
    var trigger = TriggerBuilder.Create()
                .WithIdentity("a-trigger", "a-group")
                .ForJob(SomeJob.Key)
                .StartNow()
                .Build();

    await schedule.ScheduleJob(trigger, ct)
}
// 设置当前作业的触发器时
public async Task DoSomething(IScheduler schedule, CancellationToken ct)
{
    await schedule.TriggerJob(SomeJob.Key, ct)
}
Trigger

​ 使用TriggerUtils进行触发器时间上的操作

  1. 根据触发器获得执行时间列表

    static IReadOnlyList ComputeFireTimes(IOperableTrigger trigg, ICalendar? cal, int numTimes)

    // 设置时间
    DateTimeOffset startCalendar = DateBuilder.DateOf(9, 30, 17, 1, 1, 2023);
    // 设置日期的触发器,间隔90天执行一次,从2023-01-01 17:30:09开始
    var dailyTrigger = new CalendarIntervalTriggerImpl
    {
        StartTimeUtc = startCalendar,
        RepeatIntervalUnit = IntervalUnit.Day,
        RepeatInterval = 90 // every ninety days
    };
    // 2023年1月1日加上360天 4*90 四个90天的循环
    DateTimeOffset targetCalendar = startCalendar.AddDays(360); 
    // 获得从0开始的6次循环(0-5)
    var fireTimes = TriggerUtils.ComputeFireTimes(dailyTrigger, null, 6);
    // 获得第五次的循环日期,2023-01-01 17:30:09当天也会执行一次
    DateTimeOffset fifthTime = fireTimes[4]; // get the fifth fire time
    // 两次获得的日期相同
    Assert.AreEqual(targetCalendar, fifthTime, "Day increment result not as expected.");
    
  2. 获得触发器最后一次执行的时间

    static DateTimeOffset? ComputeEndTimeToAllowParticularNumberOfFirings(IOperableTrigger trigger, ICalendar? calendar, int numberOfTimes)

    // 设置时间
    DateTimeOffset startCalendar = DateBuilder.DateOf(9, 30, 17, 1, 1, 2023);
    // 设置日期的触发器,间隔90天执行一次,从2023-01-01 17:30:09开始
    var dailyTrigger = new CalendarIntervalTriggerImpl
    {
        StartTimeUtc = startCalendar,
        RepeatIntervalUnit = IntervalUnit.Day,
        RepeatInterval = 90 // every ninety days
    };
    // 2023年1月1日加上360天 4*90 四个90天的循环
    DateTimeOffset targetCalendar = startCalendar.AddDays(360);
    // 获得从0开始的4次循环(0-3),然后返回第四次执行的时间
    var endFireTimes = TriggerUtils.ComputeFireTimes(dailyTrigger, null, 4);
    // 两次获得的日期相同
    Assert.AreEqual(targetCalendar, fifthTime, "Day increment result not as expected.");
    
  3. 在两个日期之间触发器执行的时间列表

    static IReadOnlyList ComputeFireTimesBetween(IOperableTrigger trigg, ICalendar? cal, DateTimeOffset from, DateTimeOffset to)

    // 设置触发器
    var trigger = (IOperableTrigger) TriggerBuilder.Create()
        .WithDailyTimeIntervalSchedule(x => x
            .InTimeZone(TZConvert.GetTimeZoneInfo("GTB Standard Time"))
            // 每天从0点开始
            .StartingDailyAt(new TimeOfDay(0, 0, 0))
            // 跳过21点,第二次循环跳过了20和21点
            .EndingDailyAt(new TimeOfDay(22, 0, 0))
            // 15分钟循环一次
            .WithInterval(15, IntervalUnit.Minute)
            // 触发失效什么也不做
            .WithMisfireHandlingInstructionDoNothing()
        )
    .Build();
    var from = new DateTimeOffset(2023, 1, 31, 0, 0, 0, TimeSpan.Zero);
    var to = new DateTimeOffset(2023, 2, 2, 0, 0, 0, TimeSpan.Zero);
    //理论上会执行 ((23个小时+22个小时)*60分钟)/(15分钟/次) - 1次 = 179次
    var times = TriggerUtils.ComputeFireTimesBetween(trigger, null, from, to);
    // 小于200次
    Assert.That(times.Count, Is.LessThan(200));
    
ADO.NET JobStore
  1. 使用Quartz.NET的API写入数据库,不要直接操作数据库表
  2. 死锁
    • 触发器中的作业未被正确执行
  3. 集群之间的问题
    • 非集群与集群不能共用一个数据库
  4. 数据源连接大小
    • 建议将数据源最大连接大小配置为至少为线程池中的工作线程数加上三
    • 如果使用Api则需要额外的连接
Daylight Savings Time

​ 夏令时-中国在执行了6年就取消了,因此该最佳实现目前不适用于无夏令时的地区。

​ 因为SimpleTriggers为精确到毫秒,因此不受夏令时的影响;CronTriggers在转换的时候会受到夏令时的影响,可能会多触发一次;CalenderIntervalTrigger也会受影响,会导致偏移一小时的误差。

Jobs
  • 长时间运行的作业会阻止其他线程运行(例如已运行作业数量与线程池数量相等)
  • 不建议在作业中使用Thread.Sleep(),因为他会让线程一直被占用,建议在使用Sleep的位置重新安排自身或者其他作业来替代等待(通常等待是因为条件不为true,因此可以将该判断作为作业执行,周期短)
  • 因为作业是周期性的,因此当作业异常时会一直触发异常,此时异常过多会导致应用程序不稳定。建议在catch处解决异常或重新开启新的作业来消解异常的发生。
Listener
  • 不建议监听中执行大量工作,因为作业更合适做这些工作,监听只是监听。
  • 同Jobs的异常处理,异常多了容易崩溃。
对外调用
  • 不建议对外暴露,对于本机过于危险(例如NativeJob和SendEmailJob都可以用于恶意的目的)

标签:DateTimeOffset,触发器,Quartz,作业,Practices,2023,var,90,Net
From: https://www.cnblogs.com/wanghun315/p/17082947.html

相关文章

  • 通过 web deploy 发布 .net 网站到IIS
    安装webdeploy参考博客:https://www.jianshu.com/p/519f827b660b注意一点:webdeploy官网下载的中文版本是3.6的,会出现安装不上的情况。请使用英文版的,4.0版本......
  • nnU-Net学习笔记(一):论文阅读
    nnU-Net学习笔记(一):论文阅读源码地址:https://github.com/MIC-DKFZ/nnUNet论文:https://arxiv.org/abs/1809.104861.动机:最近的网络修改在特定适用于某些问题(过拟合),......
  • C#.NET 前端大文件上传
    ​ IE的自带下载功能中没有断点续传功能,要实现断点续传功能,需要用到HTTP协议中鲜为人知的几个响应头和请求头。 一. 两个必要响应头Accept-Ranges、ETag     ......
  • ASP.NET 前端大文件上传
    ​ 以ASP.NETCoreWebAPI 作后端 API ,用 Vue 构建前端页面,用 Axios 从前端访问后端 API,包括文件的上传和下载。 准备文件上传的API #region 文件上传......
  • .net升级7.0报错1. MySqlConnection is already in use. See https://fl.vu/mysql-con
    框架升级到7.0后,经常出现服务崩溃的问题,频繁到几乎五分钟一次...然后开始盯日志,得到以下下几种异常:MySqlConnectionisalreadyinuse.Seehttps://fl.......
  • .NET7 中使用MailKit
    MailKit正式替换了.NET的SmtpClient可参考:SmtpClient类(System.Net.Mail)|MicrosoftLearnstaticvoidSendMail(stringsubject,stringhtml)......
  • netcore之异步并不是多线程!
    1、遇到await,线程的变化遇到await会把当前线程返回且返回值就是await后面的Task,再从线程池随机取一个线程往下执行代码。我们使用封装好的异步方法模拟写入大量字符串的......
  • 【计算机网络】Stanford CS144 Lab0 : networking warmup 学习记录
    CS144官方镜像:https://cs144.github.io/kangyupl备份的镜像:https://kangyupl.gitee.io/cs144.github.io/实验准备Ubuntu18.04.6LTSx86_64(实验提供)gcc8......
  • ASP.Net 8将提供路由语法高亮提示
    .NET8将为所有路由提供路由语法高亮显示,包括minimalAPI、MVC、WebAPI、Razor页面和Blazor中的路由。路由语法高亮显示依赖于在代码库中应用的StringSyntax属性......
  • kubernetes对接NFS动态存储
    存储PK根据不同的场景,可以考虑用Ceph、GlusterFS或NFS来存储Kubernetes数据。Ceph有较强的性能和容错能力,通常适用于中小规模的Kubernetes组件;GlusterFS具有可伸缩性,适用......