Quartz.Net 主要概念介绍和吐槽
我们经常遇到需要定时执行某些任务的情况,比如清理缓存、异步结果轮询等,如果不打算造轮子,那么选择一款合适的定时任务组件就很关键了。所幸,.Net 世界中的选项并不多:)
选型
主要有以下四款:
Quartz.Net
:移植自 Java 生态的Quartz
,久经考验、成熟稳重,只是个人感觉有点过度设计,初次接触容易让人困惑;Coravel
:提供任务调度,缓存,排队,邮件,事件广播等功能,全面但不专一;Hangfire
:最大的特点是内置控制面板。分为社区版和商用版。github 上,这四款组件它的点赞数最多,可见其收欢迎程度。不过它更像一个定时任务管理解决方案,所涵盖的功能除任务本身,还涉及到账户管理、图表管理、告警系统等;FluentScheduler
:似乎是这四款中最易上手的,但是已经有段时间没更新了。
稳妥起见,项目前期建议选择坑少、专注、轻量、社区较为活跃的组件 Quartz.Net,再择机使用 Hangfire 打造一个任务管理中心。
如前所述,Quartz.Net 有过度设计的嫌疑,2.x 版本时期配置方式的杂乱可见一斑。虽然现在已经迭代到 3.x,一些概念还是需要花心思理解下。
主要概念
我们围绕下面这个代码片段展开:
var schedulerFactory = builder.Services.GetRequiredService<ISchedulerFactory>();
var scheduler = await schedulerFactory.GetScheduler();
// define the job and tie it to our HelloJob class
var job = JobBuilder.Create<HelloJob>()
.WithIdentity("myJob", "group1")
.UsingJobData("way", "email")
.Build();
// Trigger the job to run now, and then every 40 seconds
var trigger = TriggerBuilder.Create()
.WithIdentity("myTrigger", "group1")
.StartNow()
.WithSimpleSchedule(x => x
.WithIntervalInSeconds(40)
.RepeatForever())
.Build();
await scheduler.ScheduleJob(job, trigger);
Jobs and Triggers
Quartz.Net 将任务业务逻辑(Jobs)和任务执行时间计划(Triggers)做了分离。官方的解释是两者可以独立管理,还可以多个 Trigger 触发同一个 Job;有没有必要见仁见智。
Job 和 Trigger 还有group
的概念,比如多个模块都有各自清理缓存的任务,可以将这些任务划分为同一个组。但是在实操过程中,group 除了语义上的指示,似乎并没有直接的其它作用;也许它可以用于业务端的扩展,不过私以为组件不应将可能的业务需求作为自己的设计点,且业务扩展不应依赖某个具体组件。
JobDetail
上述代码中变量 job 的类型并非IJob
,而是IJobDetail
,也就是说,Quartz.Net 调度维持的是 IJobDetail 实例,而 Job 实例,是在每次任务执行的时间点实例化的,执行完就销毁,实例状态并不能延续,需要借助 IJobDetail 实例存取每次执行后更新的状态。
JobDataMap
Job 实例状态保存在 JobDataMap 中,构造 JobDetail 对象时使用 .UsingJobData(key, value) 定义键值对。Trigger 也有 JobDataMap,是为上面提到的———多个 Trigger 触发同一个 Job——这种情况设计的。
使用方式如下:
public class HelloJob : IJob
{
public async Task Execute(IJobExecutionContext context)
{
JobKey key = context.JobDetail.Key;
// 可使用 context.MergedJobDataMap 同时获取 Trigger 提供的键值
JobDataMap dataMap = context.JobDetail.JobDataMap;
string way = dataMap.GetString("way");
await Console.Error.WriteLineAsync("Instance " + key + " of HelloJob is send by: " + way);
}
}
另外要注意的是,用来修饰 Job 类的特性DisallowConcurrentExecution
,其实约束的是 JobDetail,即对于 JobDetail-A,同一时间,只能有一个 Job 使用它。也就是说,可以同时激活多个 HelloJob 对象,只要它们关联的 JobDetail 不同即可(当然了,实际我们也只能操作多个不同的 JobDetail 去激活对应的 Job)。
关于 JobDetail 的解释,官方文档写得过于复杂,其实它的目的就是为了解决 Job 实例并非单例的问题,那么作者为什么不干脆将 Job 实例单例化呢?根本没必要创造一个多余的 JobDetail 的概念,令人费解。如果是因为并发考量,那么应该从 Job 定义入手,加入多线程支持。
如果项目中使用了 IOC,那么我们可以选择不使用 JobDataMap,而是将实例状态保存在自定义对象中,在每次实例化 Job 对象时注入。
Misfire 处理方案
当一个 Job 在规定时间点没有被触发执行(比如线程池里面没有可用的线程、Job 被暂停等),且超时时间超过 misfireThreshold 配置的值(默认为60秒),则作业会被调度程序认为Misfire
。
当系统恢复后(有空闲线程、Job 被恢复等),调度程序会根据配置的 Misfire 策略处理已错过的那些触发点。
参考资料
Quartz.Net 主要概念介绍和吐槽的更多相关文章
- 【Oracle 集群】ORACLE DATABASE 11G RAC 知识图文详细教程之集群概念介绍(一)
集群概念介绍(一)) 白宁超 2015年7月16日 概述:写下本文档的初衷和动力,来源于上篇的<oracle基本操作手册>.oracle基本操作手册是作者研一假期对oracle基础知识学习 ...
- Linux LVM硬盘管理之一:概念介绍
一.LVM概念介绍: LVM是 Logical Volume Manager(逻辑卷管理)的简写,它由Heinz Mauelshagen在Linux 2.4内核上实现.LVM将一个或多个硬盘的分区在逻 ...
- Java SE/ME/EE的概念介绍
转自 Java SE/ME/EE的概念介绍 多数编程语言都有预选编译好的类库以支持各种特定的功能,在Java中,类库以包(package)的形式提供,不同版本的Java提供不同的包,以面向特定的应用. ...
- rocketMq概念介绍
rocketMq官网 http://rocketmq.apache.org/ rocketMq逻辑概念介绍 rocketMq逻辑图 备注: 改图片分享自李占卫的网上家园 说明: 在rocketM ...
- java 并发多线程 锁的分类概念介绍 多线程下篇(二)
接下来对锁的概念再次进行深入的介绍 之前反复的提到锁,通常的理解就是,锁---互斥---同步---阻塞 其实这是常用的独占锁(排它锁)的概念,也是一种简单粗暴的解决方案 抗战电影中,经常出现为了阻止日 ...
- Airflow Python工作流引擎的重要概念介绍
Airflow Python工作流引擎的重要概念介绍 - watermelonbig的专栏 - CSDN博客https://blog.csdn.net/watermelonbig/article/de ...
- spring batch (一) 常见的基本的概念介绍
SpringBatch的基本概念介绍 内容来自<Spring Batch 批处理框架>,作者:刘相. 一.配置文件 在项目中使用spring batch 需要在配置文件中声明: 事务管理器 ...
- helm-chart-1-简单概念介绍-仓库搭建-在rancher上的使用
简单的概念介绍: Chart是helm管理的应用的打包格式,一个chart对应一个或一套应用.内部是一系列的yaml描述文件,以为为yaml 服务的文件. 三个部分,helm .tiller.repo ...
- Netty重要概念介绍
Netty重要概念介绍 Bootstrap Netty应用程序通过设置bootstrap(引导)类开始,该类提供了一个用于网络成配置的容器. 一种是用于客户端的Bootstrap 一种是用于服务端的S ...
- 《AngularJS深度剖析与最佳实践》笔记: 第二章 概念介绍
第二章 概念介绍 2.1 什么是UI? 用户界面包括内容(静态信息+动态信息), 外观, 交互. 在前端技术栈中分别由HTML, CSS和JS负责. 进一步抽象, 分别对应于MVC三个主要部分: Mo ...
随机推荐
- windows 使用ACR122U-A9设备读写M1卡
软件地址 M1卡服务程序 安装好驱动后就可以破解,破解成功后的秘钥会显示出来(记录下来),同级目录会生成一个dump文件,这个文件包含此M1卡的全部数据,可以使用hexedit打开,编辑或修改 Mif ...
- variant conversion error for variable:v8
oracle 添加表数据报错:variant conversion error for variable:v8. 是数据类型不匹配.
- 《浅谈亚 log 数据结构在 OI 中的应用》阅读随笔
这篇又长长长了! \(8435\to 8375\to 9729\) 早就馋这篇了!终于学了( 压位 Trie 确实很好写啊 但是总感觉使用范围不是很广的样子 似乎是见的题少 原文里都在用 \(\log ...
- 基于Nginx搭建WebDAV服务
title: 基于Nginx搭建WebDAV服务 categories: - [IT,网络,服务] tags: - WebDAV - Nginx comments: true date: 2022-1 ...
- 使用WPF或AspNetCore创建简易版ChatGPT客户端,让ChatGPT成为你的私人助理
前言:前一天写的一个ChatGPT服务端,貌似大家用起来还不是那么方便,所以我顺便用WPF和AspNetCore的webapi程序做个客户端吧,通过客户端来快速访问chatgpt模型生成对话. 1 ...
- 学习ASP.NET Core Blazor编程系列十七——文件上传(上)
学习ASP.NET Core Blazor编程系列文章之目录 学习ASP.NET Core Blazor编程系列一--综述 学习ASP.NET Core Blazor编程系列二--第一个Blazor应 ...
- 从面试题入手,畅谈 Vue 3 性能优化
前言 今年又是一个非常寒冷的冬天,很多公司都开始人员精简.市场从来不缺前端,但对高级前端的需求还是特别强烈的.一些大厂的面试官为了区分候选人对前端领域能力的深度,经常会在面试过程中考察一些前端框架的源 ...
- nuxt 登录注册加重置密码
<!-- 登录弹框 --> <div class="mask" v-show="flag"> <div class="m ...
- [seaborn] seaborn学习笔记10-绘图实例(2) Drawing example(2)
文章目录 10 绘图实例(2) Drawing example(2) 1. Grouped violinplots with split violins(violinplot) 2. Annotate ...
- Unix 系统数据文件那些事儿
前言 Unix like 系统和 windows 的最大区别就是有一套标准的系统信息数据文件,一般存放在 /etc/ 目录下,并且提供了一组近似的接口访问和查询信息,这些基础设施让系统管理看起来井井有 ...