Quartz.Net 组件的封装使用
Quartz.Net是面向.NET的一款功能齐全的开源作业调度组件,你可以把它嵌入你的系统中实现作业调度,也可以基于Quartz.Net开发一套完整的作业调度系统。它既支持简单的timer
,也支持灵活强大的corn表达式
。本文提供了一种把Quartz.Net嵌入项目中的实现。你可以看到系统其它项目与用于作业调度的项目解耦,这样做可以实现一次封装,多系统使用。
1、环境
- 操作系统:Windows 10
- IDE:Visual Studio 2019-16.8.3
- .Net Core版本:.NET 5.0
2、创建项目,添加引用
创建一个空解决方案Theo.QuartzDemo
,然后开始添加新项目。
2.1、创建名为Theo.Business
的类库项目
创建.Net Core
类库项目Theo.Business
,代表系统的业务项目。添加Microsoft.Extensions.Logging
引用。
添加IProviderDemo
接口,定义两个方法分别提供发邮件和发短信服务。你可能觉得发邮件和发短信服务不应该在同一个provider
中,但是作为示例,我偷了个懒。
IProviderDemo.cs:
using System;
namespace Theo.Business
{
public interface IProviderDemo
{
/// <summary>
/// 模拟提供发邮件服务
/// </summary>
/// <param name="param">参数</param>
void AutoSendMail(string param);
/// <summary>
/// 模拟提供发短信服务
/// </summary>
/// <param name="param">参数</param>
void AutoSendSMS(string param);
}
}
添加IProviderDemo
的实现:ProviderDemo
using Microsoft.Extensions.Logging;
using System;
namespace Theo.Business
{
///<summary>
/// 模拟业务逻辑
///</summary>
public class ProviderDemo : IProviderDemo
{
private readonly ILogger<ProviderDemo> _logger;
/// <summary>
/// .ctor
/// </summary>
/// <param name="logger"></param>
public ProviderDemo(ILogger<ProviderDemo> logger)
{
_logger = logger;
}
/// <summary>
/// 模拟提供发邮件服务
/// </summary>
/// <param name="param">参数</param>
public void AutoSendMail(string param)
{
_logger.LogError($"[{DateTimeOffset.Now:HH:mm:ss.fff}]\t{nameof(AutoSendMail)}\tparam:{param}");
}
/// <summary>
/// 模拟提供发短信服务
/// </summary>
/// <param name="param">参数</param>
public void AutoSendSMS(string param)
{
_logger.LogInformation($"[{DateTimeOffset.Now:HH:mm:ss.fff}]\t{nameof(AutoSendSMS)}\tparam:{param}");
}
}
}
2.2、添加名为Theo.TaskScheduler
的Worker Service
(辅助角色服务)项目
创建Theo.TaskScheduler
项目,用于作业调度
添加引用
Install-Package Microsoft.Extensions.Hosting.Systemd
Install-Package Microsoft.Extensions.Hosting.WindowsServices
Install-Package Quartz.AspNetCore
Install-Package Microsoft.Extensions.Logging.Log4Net.AspNetCore
Install-Package System.Text.Json
- Microsoft.Extensions.Hosting.Systemd:用以支持Linux守护进程,部署在Linux平台时需要此组件
- Microsoft.Extensions.Hosting.WindowsServices:用以支持Windows服务,部署在Windows平台时需要此组件
- Quartz.AspNetCore:.Net Core平台的Quartz组件
- Microsoft.Extensions.Logging.Log4Net.AspNetCore:Log4Net日志组件,当然也可以是Nlog/Serilog等其他任意组件
- 添加对Theo.Business项目的引用
3、封装Quartz.Net
在Theo.TaskScheduler
项目中封装Quartz.Net。封装的主要目的是为了更方便的配置作业调度计划。实现过程中的工作量主要在读取配置并交给Quartz.Net组件,以告诉组件如何根据配置去调用指定方法。
新建Models
文件夹,文件夹下新建JobModel
、JobGroupModel
和ScheduleModel
三个类。
* JobModel:计划任务job模型
* JobGroupModel:计划任务job组模型
* ScheduleModel:作业调度模型
新建IOCHelper
文件,注入业务代码(IProviderDemo),并暴露IServiceProvider
。
新建Quartz
文件夹,文件夹下新建:
- QuartzJob:实现
Quartz.IJob
的Execute
方法,来调用配置的作业调度。因为Quartz.AspNetCore
目前对IOC
的支持有限,这里实现一个protected void Init(ILogger logger, IServiceProvider serviceProvider)
方法,以便在Execute
方法中记录日志以及通过IServiceProvider
发现服务。Execute
方法的逻辑:- 从
IJobExecutionContext
读取配置 - 通过
IServiceProvider
发现服务 - Invoke调用
- 从
- BlockedJob:继承
QuartzJob
,类添加[DisallowConcurrentExecution]
属性,指定为阻塞模式job。例如某个job调用频率是每分钟1次,本次调用时发现上次调用还未执行结束,将放弃本次调用且不会抛出任何异常 - ConcurrentJob:继承
QuartzJob
,可并发执行job,不管上次执行是否结束,到时间就重新调用执行
新建QuartzWorker
类,继承BackgroundService
并重载StopAsync
和ExecuteAsync
方法。完成读取作业调度配置文件并交给Quartz.Net
组件的工作。通过appsetting.json
文件Quartz:Config
配置找到作业调度配置文件路径,读取配置文件。配置文件支持xml
、json
两种格式二选一。根据Quartz:Watch
配置确定是否监控配置文件变化。如果Quartz:Watch
配置为true,在服务运行过程中可以通过修改作业调度配置文件来修改作业调度计划。
新建Configs
文件夹,文件夹下新建SchedulerConfig.json
或者SchedulerConfig.xml
配置文件,用以配置作业调度计划。SchedulerConfig.json
配置示例如下,发邮件服务调用频率为从5秒开始每10秒钟一次,发短信服务调用频率为从0秒开始每10秒钟一次。
{
"GroupList": [
{
"Name": "JobGroup",
"JobList": [
{
"Disabled": false,
"Desc": "发邮件服务",
"Name": "SendMail",
"Cron": "5/10 * * * * ? *",
"DllName": "Theo.Business",
"ClassName": "Theo.Business.IProviderDemo",
"MethodName": "AutoSendMail"
},
{
"Disabled": false,
"Desc": "发短信服务",
"Name": "SendSMS",
"Cron": "0/10 * * * * ? *",
"DllName": "Theo.Business",
"ClassName": "Theo.Business.IProviderDemo",
"MethodName": "AutoSendSMS"
}
]
}
]
}
appsetting.json
添加配置,指定作业调度配置文件:
...
"Quartz": {
"Config": "Configs/SchedulerConfig.json",
"Watch": true
}
...
4、配置Program
并测试运行
Program.cs
文件:
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System;
using Theo.TaskScheduler.Quartz;
namespace Theo.TaskScheduler
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseWindowsService() //支持Windows服务, 其他平台自动忽略
.UseSystemd() //支持Linux守护进程,其他平台自动忽略
//使用log4net日志组件,并指定配置文件
.ConfigureLogging(conf => conf.AddLog4Net("Configs/log4net.config"))
.ConfigureAppConfiguration((hostContext, config) =>
{
config.SetBasePath(AppContext.BaseDirectory);
var env = hostContext.HostingEnvironment;
if (env.IsDevelopment())
{
config.AddJsonFile("appsettings.Development.json");
}
else
{
config.AddJsonFile("appsettings.json");
}
})
.ConfigureServices((hostContext, services) =>
{
IOCHelper.InjectDependencies(services);
services.AddHostedService<QuartzWorker>();
});
}
}
启动调试之前还需要为Log4Net
日志组件添加配置文件。根据Program.cs
中指定的配置文件Configs/log4net.config
,我们在项目Configs
文件夹下添加文件log4net.config
。具体的配置规则您可以去 log4net官网 查找,篇幅所限,本文不做说明。
终于可以F5
启动调试,结果如下图所示。
我们的作业调度配置:SendMail
从5秒开始每10秒钟一次,SendSMS
从0秒开始每10秒钟一次。从下图可以看出,作业调度运行情况和我们预期的一致。
在运行中,我们把SendMail
作业改为从1秒开始每10秒钟一次,把SendSMS
作业禁用,然后新增一个名为SendSMS-1
的作业,调用频率为从0秒开始每3秒钟一次。从下图可以看出(``开始),程序检测到了配置文件的变化,并启用的新的作业调度计划。
5、部署服务
部署到Linux平台的方法,您可以参阅官方文档:
若要部署到Windows平台,您可以发布Theo.TaskScheduler
项目,然后通过执行shell命令或者把命令包装成.bat
文件并执行的方式安装为Windows服务并启动。参考命令如下:
@echo.服务启动......
@echo off
@sc create TheoTaskScheduler binPath= "publish\Theo.TaskScheduler.exe"
@sc description TheoTaskScheduler "TheoDemo-任务调度服务"
@net start TheoTaskScheduler
@echo off
@echo.启动完毕!
@pause
6、总结
本文介绍了Quartz.Net
组件在DotNetCore
平台封装使用的详细步骤。
把Quartz.AspNetCore
封装到了单独DotNetCore项目中,与其他业务代码解耦。并实现了作业调度计划的配置化,和服务运行中实时监控配置文件功能。可以在运行中动态禁用/启用作业,添加新的作业,修改现有作业的调度计划(cron表达式)。
上文有提到示例中实现了可以指定是否允许并行调用作业的功能(BlockedJob/ConcurrentJob),但因篇幅所限并未贴出测试结果。
展望:
1、在大型项目中,调度服务可能以集群或者分布式架构的形式运行。这就要考虑把作业调度计划配置到数据库或者redis等缓存中。服务启动时候从数据库或者缓存中加载作业调度计划,并订阅修改作业调度计划事件,以便在调度计划发生改变时及时更新。
2、本例仅实现了调度服务运行中实时禁用/启用作业,添加新的作业,修改现有作业的调度计划的功能,以满足基本使用需求。如果您有兴趣/需求,可以自行探索如何实时修改是否允许并行调用作业等功能。
示例代码已上传至资源库,仅需5积分,感谢您的支持:Theo.QuartzDemo源码
Quartz.Net 组件的封装使用Quartz.AspNetCore的更多相关文章
-
ASP.NET MVC(C#)和Quartz.Net组件
ASP.NET MVC(C#)和Quartz.Net组件 在之前的文章<推荐一个简单.轻量.功能非常强大的C#/ASP.NET定时任务执行管理器组件–FluentScheduler>和&l ...
-
控制台基于Quartz.Net组件实现定时任务调度(一)
前言: 你曾经需要应用执行一个任务吗?比如现在有一个需求,需要每天在零点定时执行一些操作,那应该怎样操作呢? 这个时候,如果你和你的团队是用.NET编程的话,可以考虑使用Quartz.NET调度器.允 ...
-
quartz.net插件类库封装(含源码)
1.前言 目录: 1.quartz.net任务调度:源码及使用文档 2.quartz.net插件类库封装 最近项目需要做一写任务作业调度的工作,最终选择了quartz.net这个插件,它提供了巨大的灵 ...
-
基于MVC 的Quartz.Net组件实现的定时执行任务调度
新建mvc项目之后,首先引用Quartz组件.工具-->NuGet包管理器-->管理解决方案的 NuGet包管理器 组件安装完成. Quartz.Net一个最简单任务至少包括三部分实现:j ...
-
MVC 使用Quartz.Net组件实现定时计划任务
最近,项目中需要执行一个计划任务,组长就让我了解一下Quartz.net 这个组件,挺简单的一个组件,实现起来特别的方便,灵活,值得推荐给大家一起学习一下这个小工具.以前我有的时候是使用定时器Time ...
-
c# Quartz.net的简单封装
分享一个以前封装的Quartz.net类. 新建一个QuartzClass类库项目.nuget控制台输入 image.png 添加Quartz.net的引用. 我们新建一个JobBase.cs文件,里 ...
-
Window服务基于Quartz.Net组件实现定时任务调度(二)
前言: 在上一章中,我们通过利用控制台实现定时任务调度,已经大致了解了如何基于Quartz.Net组件实现任务,至少包括三部分:job(作业),trigger(触发器),scheduler(调度器). ...
-
Quartz简单实现定时任务管理(SSM+Quartz)
首先你得有一个用Maven搭好的SSM框架,数据库用的Mysql,这里只有关于Quartz的部分.其实有大神总结的很好了,但做完后总有些地方不一样,所以写这篇作为笔记.这里先把大神的写的分享给大家:h ...
-
支付sdk —— 该组件为封装了 微信,支付宝,银联支付
[精品] 支付组件 简要说明该组件为封装了 微信,支付宝,银联支付, 一键快速集成,几行代码即可集成 微信,支付宝,银联支付. ## 示例: # 测试账号:1.银联支付:提供测试使用卡号.手机号信息 ...
随机推荐
-
easyUI属性汇总
CSS类定义: 1.div easyui-window 生成一个window窗口样式. 属性如下: 1)modal:是否生成模态窗口.true[是] false[否] 2)shadow:是否显示窗口阴 ...
-
[译]MVC网站教程(三):动态布局和站点管理
目录 1. 介绍 2. 软件环境 3. 在运行示例代码之前(源代码 + 示例登陆帐号) 4. 自定义操作结果和控制器扩展 1) OpenFileResult 2) ImageR ...
-
Linux下调试程序方法
您可以用各种方法来监控运行着的用户空间程序:可以为其运行调试器并单步调试该程序,添加打印语句,或者添加工具来分析程序.本文描述了几种可以用来调试在 Linux 上运行的程序的方法.我们将回顾四种调试问 ...
-
GNU Makefile编写
[Introduction] make 是程序员很好用的工具,如果存在makefile存在,每次更新代码,执行shell命令 shell 就可以执行所有需要编译的文件,make是根据你编写的Makef ...
-
.net开发笔记(十三) Winform常用开发模式第一篇
上一篇博客最后我提到“异步编程模型”(APM),之后本来打算整理一下这方面的材料然后总结一下写篇文章与诸位分享,后来在整理的过程中不断的延伸不断地扩展,发现完全偏离了“异步编程”这个概念,前前后后所有 ...
-
solr多条件查询(三)
1.昨天记了一下三条件的“并且” “并且”( && && )的情况,今天再来记一下 “并且” “或者” 的情况. 这里的或者情况,一定要搞清楚无论有多少情况, ...
-
卸载openfire
首先,确保你已经关掉了openfire打开终端 (在应用程序-->实用工具-->)输入以下命令sudo rm -rf /Library/PreferencePanes/Openfire.p ...
-
Lazarus中Base64的操作
在字符串处理中,我们经常需要对文件编码然后再进行传输,通常会使用base64编码,在FreePascal中默认集成了这个单元,我们来介绍如何使用: 首先需要在引用单元的时候使用: use base64 ...
-
旧版asp.net 发送邮件代码
说到发送邮件发送,先提一下SMTP(呵呵,高手就跳过这一段吧!). SMTP的全称是“Simple Mail Transfer Protocol”,即简单邮件传输协议.它是一组用于从源地址到目的地址传 ...
-
webservice跨服务器上传附件
最近一个项目,用到文件上传功能,本来简单地使用upload控件直接post到服务器保存,简单实现了.后来考虑到分布是部署,静态附件.图片等内容要单独服务器(命名为B服务器,一台,192.168.103 ...