使用Quartz.net + Topshelf完成服务调用

news/2024/11/29 20:47:53/

概述:

Quartz.NET 是一个开源作业调度库,可用于在 .NET 应用程序中调度和管理作业。它提供了一个灵活而强大的框架,用于调度作业在特定的日期和时间或以固定的时间间隔运行,并且还支持复杂的调度场景,例如 cron 表达式。

Quartz.NET 基于Quartz 库,该库最初是用 Java 开发的。Quartz.NET 的创建是为了将Quartz的强大功能带入 .NET 平台,它已成为 .NET 应用程序中调度作业的流行选择。

Quartz.NET 的一些关键特性包括:

  • 支持根据特定日期和时间或定期安排作业
  • 支持使用cron 表达式的复杂调度场景
  • 能够安排作业在分布式环境中的特定节点上运行
  • 支持集群、故障转移和负载平衡
  • 能够将作业和触发数据保存到数据库
  • 与流行的 .NET 框架集成,例如 ASP.NET 和 Spring.NET
    以下是配置及使用过程:
官方学习文档:
http://www.quartz-scheduler.net/documentation/index.html
使用实例介绍:
https://www.quartz-scheduler.net/documentation/quartz-2.x/quick-start.html#nuget-package
官方源码下载:
https://sourceforge.net/projects/quartznet/files/quartznet/

1、根据官方源码下载地址我们找到一个文件版本进行下载
在这里插入图片描述

文件介绍:

在这里插入图片描述

文件介绍
Configuration.cs这个文件定义了Quartz.NET的配置类,包括调度器的实例化、作业存储、线程池、触发器监听器、作业监听器等配置项
IQuartzServer.cs这个文件定义了Quartz.NET的服务器接口,包括启动、停止、暂停和恢复调度器等方法
Program.cs入口程序,演示了如何使用Quartz.NET进行作业调度
quartz.config这个文件是Quartz.NET的配置文件,用于配置调度器的行为和特性,例如调度器类型、线程池大小、作业存储类型等等
quartz_jobs.xml这个文件定义了Quartz.NET的作业和触发器,包括作业名称、作业类型、触发器类型、触发器表达式等等
QuartzServer.cs这个文件实现了IQuartzServer接口,是Quartz.NET服务器的实现代码,包括调度器的启动、停止、暂停和恢复等方法
SampleJob.cs这个文件是一个示例作业,演示了如何实现一个简单的Quartz.NET作业
QuartzServerFactory.cs这个文件是Quartz.NET服务器的工厂类,用于创建和销毁Quartz.NET服务器实例

总的来说,这些文件是Quartz.NET框架的核心文件,包含了Quartz.NET的配置、调度器、作业和触发器等组件的实现。

接下来我们运行文件,可以看到quartz_job.xml文件中配置的是10秒运行一次,运行起来之后,每隔十秒会有输出
在这里插入图片描述

搭建一个Quartz,本人本地是基于.NET Framework 4.0搭建的(可使用更高版本)

1、安装下载NuGet程序包

Common.Logging 3.4.1.0
Common.Logging.Core 3.4.1.0
log4net 2.0.15.0
Quartz 2.6.2.0
Topshelf 3.3.152.0
Topshelf.Log4Net 3.3.152.0

  
Quartz:这是 Quartz.NET 的核心包,包含了调度器、作业、触发器等组件。
Common.Logging:这个包是一个通用的日志框架,Quartz.NET 使用它来记录日志。
Common.Logging.Log4Net:这个包是 Common.Logging 的 Log4Net 适配器,Quartz.NET 需要引用它来使用 Log4Net 记录日志
Topshelf:这是 Topshelf 的核心包,包含了将应用程序转换为 Windows 服务的功能。
Topshelf.Log4Net:这个包提供了 Log4Net 日志框架的支持,允许您在 Topshelf 中使用 Log4Net 记录日志。  

2、实现IJob

TimeJob.cs实现IJob,在Execute方法中编写要处理的业务逻辑,系统就会按照Quartz的配置,定时处理

using log4net;
using Quartz;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace QuartzSDS.QuartzJobs
{public sealed class TimeJob : IJob{private readonly ILog _logger = LogManager.GetLogger(typeof(TimeJob));public void Execute(IJobExecutionContext context){_logger.InfoFormat("执行TimeJob业务");Console.WriteLine($"执行TimeJob业务");}}
}

3、使用Topshelf调度任务

Topshelf调度可以查看某大佬的使用介绍,以下是文章地址 :
https://www.cnblogs.com/jys509/p/4614975.html

using System;
using Common.Logging;
using Quartz.Impl;
using Topshelf;namespace QuartzSDS
{/// <summary>/// The main server logic./// </summary>public class QuartzServer : ServiceControl, IQuartzServer{private readonly ILog logger;private ISchedulerFactory schedulerFactory;private IScheduler scheduler;/// <summary>/// Initializes a new instance of the <see cref="QuartzServer"/> class./// </summary>public QuartzServer(){logger = LogManager.GetLogger(GetType());}/// <summary>/// Initializes the instance of the <see cref="QuartzServer"/> class./// </summary>public virtual void Initialize(){try{				schedulerFactory = CreateSchedulerFactory();scheduler = GetScheduler();}catch (Exception e){logger.Error("Server initialization failed:" + e.Message, e);throw;}}/// <summary>/// Gets the scheduler with which this server should operate with./// </summary>/// <returns></returns>protected virtual IScheduler GetScheduler(){return schedulerFactory.GetScheduler();}/// <summary>/// Returns the current scheduler instance (usually created in <see cref="Initialize" />/// using the <see cref="GetScheduler" /> method)./// </summary>protected virtual IScheduler Scheduler{get { return scheduler; }}/// <summary>/// Creates the scheduler factory that will be the factory/// for all schedulers on this instance./// </summary>/// <returns></returns>protected virtual ISchedulerFactory CreateSchedulerFactory(){return new StdSchedulerFactory();}/// <summary>/// Starts this instance, delegates to scheduler./// </summary>public virtual void Start(){try{scheduler.Start();}catch (Exception ex){logger.Fatal(string.Format("Scheduler start failed: {0}", ex.Message), ex);throw;}logger.Info("Scheduler started successfully");}/// <summary>/// Stops this instance, delegates to scheduler./// </summary>public virtual void Stop(){try{scheduler.Shutdown(true);}catch (Exception ex){logger.Error(string.Format("Scheduler stop failed: {0}", ex.Message), ex);throw;}logger.Info("Scheduler shutdown complete");}/// <summary>/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources./// </summary>public virtual void Dispose(){// no-op for now}/// <summary>/// Pauses all activity in scheduler./// </summary>public virtual void Pause(){scheduler.PauseAll();}/// <summary>/// Resumes all activity in server./// </summary>public void Resume(){scheduler.ResumeAll();}/// <summary>/// TopShelf's method delegated to <see cref="Start()"/>./// </summary>public bool Start(HostControl hostControl){Start();return true;}/// <summary>/// TopShelf's method delegated to <see cref="Stop()"/>./// </summary>public bool Stop(HostControl hostControl){Stop();return true;}/// <summary>/// TopShelf's method delegated to <see cref="Pause()"/>./// </summary>public bool Pause(HostControl hostControl){Pause();return true;}/// <summary>/// TopShelf's method delegated to <see cref="Resume()"/>./// </summary>public bool Continue(HostControl hostControl){Resume();return true;}}
}

4、程序入口

using Quartz;
using Quartz.Impl;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Timers;
using Topshelf;namespace QuartzSDS
{class Program{static void Main(string[] args){log4net.Config.XmlConfigurator.ConfigureAndWatch(new FileInfo(AppDomain.CurrentDomain.BaseDirectory + "log4net.config"));HostFactory.Run(x =>{x.UseLog4Net();x.Service<QuartzServer>();x.SetDescription("QuartzSDS集成平台调用");x.SetDisplayName("QuartzSDS");x.SetServiceName("QuartzSDS集成平台接口调用");x.EnablePauseAndContinue();});}}
}

5、配置quartz.config、quartz_jobs.xml、log4net.config

说明:这三个文件,分别选中→右键属性→复制到输入目录设为:始终复制,如图:
在这里插入图片描述
quartz.config文件

# You can configure your scheduler in either <quartz> configuration section
# or in quartz properties file
# Configuration section has precedencequartz.scheduler.instanceName = QuartzTest# configure thread pool info
quartz.threadPool.type = Quartz.Simpl.SimpleThreadPool, Quartz
quartz.threadPool.threadCount = 10
quartz.threadPool.threadPriority = Normal# job initialization plugin handles our xml reading, without it defaults are used
quartz.plugin.xml.type = Quartz.Plugin.Xml.XMLSchedulingDataProcessorPlugin, Quartz
quartz.plugin.xml.fileNames = ~/quartzJobs.xml# export this server to remoting context
#quartz.scheduler.exporter.type = Quartz.Simpl.RemotingSchedulerExporter, Quartz
#quartz.scheduler.exporter.port = 555
#quartz.scheduler.exporter.bindName = QuartzScheduler
#quartz.scheduler.exporter.channelType = tcp
#quartz.scheduler.exporter.channelName = httpQuartz

quartzJobs.xml

<?xml version="1.0" encoding="UTF-8"?><!-- This file contains job definitions in schema version 2.0 format --><job-scheduling-data xmlns="http://quartznet.sourceforge.net/JobSchedulingData" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0"><processing-directives><overwrite-existing-data>true</overwrite-existing-data></processing-directives><schedule><job><!--name(必填) 任务名称,同一个group中多个job的name不能相同,若未设置group则所有未设置group的job为同一个分组,如:<name>sampleJob</name>--><name>TimeJob</name><!--group(选填) 任务所属分组,用于标识任务所属分组,如:<group>sampleGroup</group>--><group>Time</group><!--description(选填) 任务描述,用于描述任务具体内容,如:<description>Sample job for Quartz Server</description>--><description>TimeJob执行调度</description><!--job-type(必填) 任务类型,任务的具体类型及所属程序集,格式:实现了IJob接口的包含完整命名空间的类名,程序集名称,如:<job-type>Quartz.Server.SampleJob, Quartz.Server</job-type>--><job-type>QuartzSDS.QuartzJobs.TimeJob,QuartzSDS</job-type><!--durable(选填) 具体作用不知,官方示例中默认为true,如:<durable>true</durable>--><durable>true</durable><!--recover(选填) 具体作用不知,官方示例中默认为false,如:<recover>false</recover>--><recover>false</recover></job><trigger><cron><!--name(必填) 触发器名称,同一个分组中的名称必须不同--><name>TimeJobTrigger</name><!--group(选填) 触发器组--><group>Time</group><!--description(选填) 触发器描述--><description>TimeJob</description><!--job-name(必填) 要调度的任务名称,该job-name必须和对应job节点中的name完全相同--><job-name>TimeJob</job-name><!--job-group(选填) 调度任务(job)所属分组,该值必须和job中的group完全相同--><job-group>Time</job-group><!--start-time(选填) 任务开始执行时间utc时间,北京时间需要+08:00,如:<start-time>2012-04-01T08:00:00+08:00</start-time>表示北京时间2012年4月1日上午8:00开始执行,注意服务启动或重启时都会检测此属性,若没有设置此属性或者start-time设置的时间比当前时间较早,则服务启动后会立即执行一次调度,若设置的时间比当前时间晚,服务会等到设置时间相同后才会第一次执行任务,一般若无特殊需要请不要设置此属性--><start-time>2023-04-01T00:00:00+08:00</start-time><!--am12点执行,pm12点执行--><cron-expression>* * 0,12 * * ? </cron-expression></cron></trigger></schedule>
</job-scheduling-data>

log4net.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration><configSections><section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/></configSections><log4net><appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender"><!--日志路径--><param name= "File" value= "E:\QuartzSDSLog\log\"/><!--是否是向文件中追加日志--><param name= "AppendToFile" value= "true"/><!--log保留天数--><param name= "MaxSizeRollBackups" value= "10"/><!--日志文件名是否是固定不变的--><param name= "StaticLogFileName" value= "false"/><!--日志文件名格式为:2008-08-31.log--><param name= "DatePattern" value= "yyyy-MM-dd&quot;.read.log&quot;"/><!--日志根据日期滚动--><param name= "RollingStyle" value= "Date"/><layout type="log4net.Layout.PatternLayout"><param name="ConversionPattern" value="%d [%t] %-5p %c - %m%n %loggername" /></layout></appender><!-- 控制台前台显示日志 --><appender name="ColoredConsoleAppender" type="log4net.Appender.ColoredConsoleAppender"><mapping><level value="ERROR" /><foreColor value="Red, HighIntensity" /></mapping><mapping><level value="Info" /><foreColor value="Green" /></mapping><layout type="log4net.Layout.PatternLayout"><conversionPattern value="%n%date{HH:mm:ss,fff} [%-5level] %m" /></layout><filter type="log4net.Filter.LevelRangeFilter"><param name="LevelMin" value="Info" /><param name="LevelMax" value="Fatal" /></filter></appender><root><!--(高) OFF > FATAL > ERROR > WARN > INFO > DEBUG > ALL (低) --><level value="all" /><appender-ref ref="ColoredConsoleAppender"/><appender-ref ref="RollingLogFileAppender"/></root></log4net>
</configuration>

6、运行项目,以上quartzJobs.xml文件中cron-expression设置的是中午12点执行一次,凌晨12点执行一次

在这里插入图片描述

7、安装、启动、卸载服务命令

1、以管理身份运行cmd
2、例如此项目是在我电脑e盘下:
安装服务:
E:\Quartz.Net集成平台接口调用\QuartzSDS\QuartzSDS\bin\Debug\QuartzSDS.exe  install启动服务:
E:\Quartz.Net集成平台接口调用\QuartzSDS\QuartzSDS\bin\Debug\QuartzSDS.exe  start卸载服务:
E:\Quartz.Net集成平台接口调用\QuartzSDS\QuartzSDS\bin\Debug\QuartzSDS.exe  uninstall

在这里插入图片描述

quartz_jobs.xml详解:

  1. <job-scheduling-data>:这是根节点,它定义了 XML 文件的命名空间和版本号,同时包含了一个或多个 <schedule> 节点。

    • xmlns:指定了 XML 文件的命名空间为 http://quartznet.sourceforge.net/JobSchedulingData

    • xmlns:xsi:指定了 XML 文件中使用的 XML Schema 命名空间,用于指定 XML 文件的格式。

    • version:指定了 XML 文件的版本号,当前版本为 2.0。

  2. <schedule>:这个节点包含了作业和触发器的定义。

    • <job>:这个节点定义了一个作业。

      • <name>:作业的名称,必须唯一。

      • <group>:作业所属的组,可以用来对作业进行分组管理。

      • <description>:作业的描述信息,可以用来描述作业的用途等。

      • <job-type>:作业的类型,是一个类的完全限定名和程序集名称的组合,用于指定作业的实现类。

        例如,在上面的示例中,作业的类型为 MyNamespace.MyJob,表示在 MyAssembly 程序集中有一个名为 MyNamespace.MyJob 的类实现了该作业。

    • <trigger>:这个节点定义了一个触发器。

      • <cron>:这个节点表示使用 Cron 表达式来指定触发器的执行时间。

        • <name>:触发器的名称,必须唯一。

        • <group>:触发器所属的组,可以用来对触发器进行分组管理。

        • <description>:触发器的描述信息,可以用来描述触发器的用途等。

        • <job-name>:触发器关联的作业的名称。

        • <job-group>:触发器关联的作业所属的组。

        • <cron-expression>:Cron 表达式,用于指定触发器的执行时间。Cron 表达式是由 7 个字段组成的,分别表示秒、分、时、日、月、周、年等时间信息。

          例如,在上面的示例中,Cron 表达式 0 0/5 * * * ? 表示每隔 5 分钟执行一次。

在配置文件中,您可以定义多个作业和触发器,以便根据配置文件中的设置执行多个作业。在加载配置文件时,Quartz.NET 将会根据作业和触发器的定义创建对应的作业和触发器,并将它们添加到调度器中,以便按照指定的时间表执行作业。

Quartz的cron表达式:
官方地址:https://www.quartz-scheduler.net/documentation/quartz-2.x/tutorial/crontrigger.html#introduction
在这里插入图片描述
Cron 表达式是一种用于指定定期执行任务的时间表达式,它由 7 个字段组成,分别表示秒、分、时、日、月、周、年等时间信息。

Cron 表达式的一般格式为:

<秒> <分> <时> <日> <月> <周> <年>

其中,<秒><分><时><日><月><周><年> 都是 0 到 59 或者 0 到 23 之间的整数值,具体含义如下:

  • <秒>:表示定时任务的秒数,取值范围为 0 到 59。

  • <分>:表示定时任务的分钟数,取值范围为 0 到 59。

  • <时>:表示定时任务的小时数,取值范围为 0 到 23。

  • <日>:表示定时任务的日期,取值范围为 1 到 31。

  • <月>:表示定时任务的月份,取值范围为 1 到 12。

  • <周>:表示定时任务的星期几,取值范围为 0 到 7,其中 0 和 7 都表示星期日。

  • <年>:表示定时任务的年份,取值范围为 1970 到 2099。

Cron 表达式中还可以使用特殊字符来表示一些特殊的时间规则,包括:

  • *:表示匹配任意值,比如 * * * * * * 表示每秒都执行一次任务。

  • ?:表示不指定值,用于代替 <日><周> 中的一个,比如 0 0 12 ? * MON-FRI 表示每周一到周五中午 12 点执行一次任务。

  • -:表示指定一个范围,比如 0 0 0 1-31 * * 表示每个月的 1 号到 31 号的零点都执行一次任务。

  • ,:表示列出多个值,比如 0 0 0 * * MON,WED 表示每周一和周三的零点都执行一次任务。

  • /:表示指定一个步长,比如 0/5 * * * * * 表示每隔 5 秒钟执行一次任务。

注意,Cron 表达式中的所有时间都是基于调度器所在的服务器的本地时间而定的。如果需要使用其他时区的时间,可以在配置文件中指定时区信息。
以上是使用Quartz.net + Topshelf完成服务调用,如有错误可指正 Thanks♪(・ω・)ノ


http://www.ppmy.cn/news/55226.html

相关文章

Yarn(Yet Another Reource Negotiator)另一个资源协调者

官网引用 总结性 产生的需求 YARN工作逻辑 通用的资源管理系统&#xff0c;为上一层应用提供统一的资源管理和调度。解决集群资源利用率&#xff0c;数据共享&#xff0c;资源管理统一问题&#xff0c;yarn取代Job Tracker角色 组件说明 Client 向RM提交任务&#xff0c;终…

【Vue 基础】尚品汇项目-03-home首页搭建(全局组件与局部组件)

1. 完成三级联动组件&#xff08;全局组件&#xff09; 由于三级联动组件在Home、Search、Detail中都需使用&#xff0c;因此将三级联动组件作为全局组件&#xff0c;这样只需要注册一次&#xff0c;就可以在项目任意地方使用。 新建“home/TypeNav/index.vue”&#xff0c;写…

TiDB Operator 和 Operator Dashboard

TiDB Operator 和 Operator Dashboard V1TiDB Operator概念实现 Operator Dashboard概念实现 V2思路实例代码TiDB ARM OperatorTiDB ARM Operator Dashboard V1 为了演示如何编写 TiDB Operator 和 Operator Dashboard&#xff0c;我们将分别介绍它们的概念和实现。 TiDB Ope…

1 Unix基础知识

1.1 登录 1.1 登录名 登录Unix系统时&#xff0c;要先输入登录名&#xff0c;然后再输入口令。系统再其口令文件&#xff08;/etc/password文件&#xff09;查看登录名。口令文件中的登录项由7个以冒号分隔的字段组成&#xff1a;登录名&#xff0c;加密口令&#xff0c;数字用…

B端产品如何搭建用户帮助体系

用户帮助体系可以提升用户的使用体验&#xff0c;引导用户正确的使用产品&#xff0c;并且体验产品的各个功能&#xff0c;B端产品因为其特殊的业务属性和复杂度&#xff0c;通常其学习成本不低。这些成本不仅仅体现在对于复杂业务概念及流程的认知方面&#xff0c;同时体现在整…

STM32物联网实战开发(1)——全新的程序框架

现在STM32公司主推的是HAL库的开发&#xff0c;标准库已经不再更新。通过STM32cubeMX的图形界面生成代码非常的方便。 一、程序框架的构想 1、STM32cubeMX 生成的代码与添加的应用代码分离&#xff1b; 2、利用 STM32cubeMX 重新生成代码&#xff0c;不影响应用代码&#xf…

03 【Sass语法介绍-嵌套】

1.前言 在企业的实际项目开发中&#xff0c;Sass 的嵌套可以说是非常非常有用的&#xff0c;它可以让你的 CSS 代码易于管理和维护&#xff0c;看起来也比较清晰&#xff0c;这也是 Sass 中很基础的一个知识点&#xff0c;首先掌握这个至关重要&#xff01;在此章节我们将学习…

tensorflow中Keras ---图像预处理----tf.keras.preprocessing.image.ImageDataGenerator 类

1.源代码&#xff1a; tf.keras.preprocessing.image.ImageDataGenerator(featurewise_centerFalse,samplewise_centerFalse,featurewise_std_normalizationFalse,samplewise_std_normalizationFalse,zca_whiteningFalse,zca_epsilon1e-06,rotation_range0,width_shift_range0…