Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What is the method of using Quartz.Net

2025-01-28 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

This article mainly explains "what is the use of Quartz.Net". Friends who are interested may wish to have a look at it. The method introduced in this paper is simple, fast and practical. Let's let the editor take you to learn "what is the use of Quartz.Net?"

During the development of the project, you will inevitably encounter tasks that need to be processed in the background, such as regularly sending email notifications, time-consuming data processing, and so on. At this time, you need Quartz.Net.

Quartz.Net is pure, it is a .net assembly and is a C # implementation of the very popular Java job scheduling system Quartz.

Quartz.Net is a fully functional task scheduling system that can be applied from small applications to large enterprise systems. The full function is reflected in the diversity of triggers, that is, simple timers and Cron expressions are supported; repetitive job tasks can be performed and exceptional calendars can be specified; tasks can also be diverse, as long as the IJob interface is inherited.

For small applications, Quartz.Net can be integrated into your system. For enterprise systems, it provides Routing support and Group to organize and manage tasks. In addition, there are persistence, plug-in functions, load balancing and fault migration to meet the needs of different application scenarios.

Hello Quartz.Net

Start using a framework, just like learning a development language, it's best to start with a Hello World program.

First create a sample program, and then add a reference to Quartz.Net.

Install-Package Quartz-Version 3.0.7

We are using the latest version 3.0.7 to demonstrate. After adding the reference, create a Job class, HelloQuartzJob.

Public class HelloQuartzJob: IJob {public Task Execute (IJobExecutionContext context) {return Task.Factory.StartNew (() = > {Console.WriteLine ("Hello Quartz.Net");});}}

This is a very simple Job class that outputs the text Hello Quartz.Net at execution time.

Next, we create a scheduler (Scheduler) when the program starts, and add a schedule for HelloQuartzJob:

Static async Task MainAsync () {var schedulerFactory = new StdSchedulerFactory (); var scheduler = await schedulerFactory.GetScheduler (); await scheduler.Start (); Console.WriteLine ($"Task Scheduler started"); / / create job and trigger var jobDetail = JobBuilder.Create () .Build () Var trigger = TriggerBuilder.Create () .WithSimpleSchedule (m = > {m.WithRepeatCount (3) .WithIntervalInSeconds (1);}) .build (); / / add scheduling await scheduler.ScheduleJob (jobDetail, trigger);}

Then run the program, and you will see the following figure:

As you can see from the demonstration, it usually takes four steps to perform a scheduled task:

Create a task scheduler. A scheduler is usually created when an application starts, and an application instance usually requires only one scheduler.

Create Job and JobDetail. Job is the type of job, which describes how the job is executed, and this class is defined by us; JobDetail is the encapsulation of the job by Quartz, which contains the Job type and the data used by Job during execution, as well as options such as whether to persist and whether to overwrite existing jobs.

Create a trigger. The trigger describes when the job is executed.

Add a schedule. When the above three steps are completed, the job can be scheduled.

Jobs: Job and JobDetail

Job is the type of job that describes how the job is executed, which is defined by us, such as HelloQuartzJob above. Job implements the IJob interface, while the IJob interface has only one Execute method, and the parameter context contains Scheduler, JobDetail, Trigger, and so on associated with the current context.

A typical Job definition is as follows:

Public class HelloQuartzJob: IJob {public Task Execute (IJobExecutionContext context) {return Task.Factory.StartNew (() = > {Console.WriteLine ("Hello Quartz.Net");});}} JobData

Job does not exist in isolation, it needs to execute parameters, how can these parameters be passed in? Let's define a Job class for demonstration.

Public class SayHelloJob: IJob {public string UserName {get; set;} public Task Execute (IJobExecutionContext context) {return Task.Factory.StartNew (() = > {Console.WriteLine ($"Hello {UserName}!");});}}

SayHelloJob requires the parameter UserName when it is executed, which is called JobData,Quartz.Net and is passed through JobDataMap. The code is as follows:

/ / create job var jobDetail = JobBuilder.Create () .SetJobData (new JobDataMap () {new KeyValuePair ("UserName", "Tom")}) .build ()

Through the SetJobData method of JobBuilder, pass in the JobDataMap object, which can contain multiple parameters, which can be mapped to the properties of the Job class. If we refine the code running example, we can see the following figure:

JobDetail

JobDetail is the encapsulation of a job by Quartz, which contains the Job type and the data used by Job during execution, as well as options such as whether to isolate storage, request a recovery job, and so on.

JobDetail is created through JobBuilder. For example:

Var jobDetail = JobBuilder.Create () .SetJobData (new JobDataMap () {new KeyValuePair ("UserName") "Tom")}) .StoreDurries (true) .RequestRecovery (true) .WithIdentity ("SayHelloJob-Tom", "DemoGroup") .WithDescription ("Say hello to Tom job") .build ()

Parameter description:

SetJobData: setting JobData

StoreDurably: orphaned storage, which means that the JobDetail will be stored even if it does not have an associated Trigger

RequestRecovery: request for recovery, which means that if the application crashes and starts again, the job will be executed again.

WithIdentity: unique identification of the job

WithDescription: job description information

In addition, Quartz.Net supports two very useful features:

DisallowConcurrentExecution: forbids parallel execution, which is effective for JobDetail

PersistJobDataAfterExecution: persists the JobData after execution is completed. This feature takes effect for the Job type, which means that all JobDetail using the Job will persist the JobData after the execution is complete.

Persistent JobData

Let's demonstrate this PersistJobDataAfterExecution feature. In SayHelloJob, we add a new field, RunSuccess, to record whether the task was executed successfully.

First add features to SayHelloJob:

[PersistJobDataAfterExecution] public class SayHelloJob: IJob {}

Then add JobData when you create the JobDetail:

Var jobDetail = JobBuilder.Create () .SetJobData (new JobDataMap () {new KeyValuePair ("UserName", "Tom"), new KeyValuePair ("RunSuccess", false)})

When Job is executed, update the value of RunSuccess:

Public Task Execute (IJobExecutionContext context) {return Task.Factory.StartNew (() = > {Console.WriteLine ($"Prev RunSuccess: {RunSuccess}"); Console.WriteLine ($"Hello {UserName}!"); context.JobDetail.JobDataMap.Put ("RunSuccess", true);});}

Next, let's take a look at the implementation effect:

Trigger: Trigger

Trigger is a trigger that is used to customize execution jobs. There are two types of Trigger: SampleTrigger and CronTrigger, which we will explain separately.

SampleTrigger

As the name implies, this is a simple trigger with the following features:

Repeat: WithRepeatCount () / RepeatForever ()

Set interval: WithInterval ()

Timing execution: StartAt () / StartNow ()

Set priority: WithPriority (), default is 5

It is important to note that when the Trigger reaches the time specified by the StartAt, it is executed once, and this time the execution is not included in the WithRepeatCount. As we can see in the example above, once the schedule is added, it is executed immediately, then repeated three times, and finally four times.

CronTrigger

CronTrigger completes the scheduling through Cron expressions. Cron expressions are very flexible and can meet the needs of almost all kinds of timing scenarios.

For Cron expressions, you can move to Quartz Cron expressions.

Examples of using CronTrigger are as follows:

Var trigger = TriggerBuilder.Create () .WithCronSchedule ("* / 1 *?") .build (); Calendar: Calendar

The Calendar can be associated with the Trigger to discharge the execution plan from the Trigger. For example, if you only want to execute your homework on a weekday, we can define a calendar for rest days, associate it with Trigger, and arrange the execution plan for rest days.

The sample code for Calendar is as follows:

Var calandar = new HolidayCalendar (); calandar.AddExcludedDate (DateTime.Today); await scheduler.AddCalendar ("holidayCalendar", calandar, false, false); var trigger = TriggerBuilder.Create () .WithCronSchedule ("* / 1 *?") .ModifiedByCalendar ("holidayCalendar") .build ()

In this example, we create a HolidayCalendar calendar and then add a date to exclude execution. After we add today to the exclusion date, the Trigger will not be triggered today.

Listener

JobListeners

TriggerListeners

SchedulerListeners

Listeners are another excellent feature of Quartz.Net, which allows us to write listeners to obtain job status and process job data at run time.

JobListener

JobListener can listen for pre-execution, post-execution, and reject events of Job execution. We demonstrate through the code:

Public class MyJobListener: IJobListener {public string Name {get;} = nameof (MyJobListener); public Task JobToBeExecuted (IJobExecutionContext context, CancellationToken cancellationToken = default) {/ / Job is about to execute return Task.Factory.StartNew (() = > {Console.WriteLine ($"Job: {context.JobDetail.Key} is about to be executed");}) } public Task JobExecutionVetoed (IJobExecutionContext context, CancellationToken cancellationToken = default) {return Task.Factory.StartNew (() = > {Console.WriteLine ($"Job: {context.JobDetail.Key} denied execution");}) } public Task JobWasExecuted (IJobExecutionContext context, JobExecutionException jobException, CancellationToken cancellationToken = default) {/ / Job execution completed return Task.Factory.StartNew (() = > {Console.WriteLine ($"Job: {context.JobDetail.Key} execution complete");}}

When the definition is complete, add the MyJobListener to the Scheduler:

Scheduler.ListenerManager.AddJobListener (new MyJobListener (), GroupMatcher.AnyGroup ())

Then we run the program, and we can see that Listener is called:

As you can see from the picture, both JobToBeExecuted and JobWasExecuted are executed, but JobExecutionVetoed is not executed, so how to trigger JobExecutionVetoed? Please continue to read the TriggerListener demo.

TriggerListener

TriggerListener can monitor the execution of Trigger, which we demonstrate through code:

Public class MyTriggerListener: ITriggerListener {public string Name {get;} = nameof (MyTriggerListener); public Task TriggerComplete (ITrigger trigger, IJobExecutionContext context, SchedulerInstruction triggerInstructionCode, CancellationToken cancellationToken = default) {return Task.CompletedTask;} public Task TriggerFired (ITrigger trigger, IJobExecutionContext context, CancellationToken cancellationToken = default) {return Task.CompletedTask;} public Task TriggerMisfired (ITrigger trigger, CancellationToken cancellationToken = default) {return Task.CompletedTask } public Task VetoJobExecution (ITrigger trigger, IJobExecutionContext context, CancellationToken cancellationToken = default) {return Task.FromResult (true); / / returns true to reject Job to continue execution}}

Add MyTriggerListener to the Scheduler:

Scheduler.ListenerManager.AddTriggerListener (new MyTriggerListener (), GroupMatcher.AnyGroup ())

You can see the following effect by running the code:

As you can see from the picture, the JobExecutionVetoed in JobListener is executed.

SchedulerListener

ISchedulerListener provides listening for Job and Trigger management. Events related to the scheduler include: adding jobs / triggers, deleting jobs / triggers, serious errors in the scheduler, notification of scheduler shutdown, and so on. The complete interface definition is as follows:

Public interface ISchedulerListener {Task JobAdded (IJobDetail jobDetail, CancellationToken cancellationToken = default); Task JobDeleted (JobKey jobKey, CancellationToken cancellationToken = default); Task JobInterrupted (JobKey jobKey, CancellationToken cancellationToken = default); Task JobPaused (JobKey jobKey, CancellationToken cancellationToken = default); Task JobResumed (JobKey jobKey, CancellationToken cancellationToken = default); Task JobScheduled (ITrigger trigger, CancellationToken cancellationToken = default); Task JobsPaused (string jobGroup, CancellationToken cancellationToken = default); Task JobsResumed (string jobGroup, CancellationToken cancellationToken = default); Task JobUnscheduled (TriggerKey triggerKey, CancellationToken cancellationToken = CancellationToken cancellationToken) Task SchedulerError (string msg, SchedulerException cause, CancellationToken cancellationToken = default); Task SchedulerInStandbyMode (CancellationToken cancellationToken = default); Task SchedulerShutdown (CancellationToken cancellationToken = default); Task SchedulerShuttingdown (CancellationToken cancellationToken = default); Task SchedulerStarted (CancellationToken cancellationToken = default); Task SchedulerStarting (CancellationToken cancellationToken = default); Task SchedulingDataCleared (CancellationToken cancellationToken = default); Task TriggerFinalized (ITrigger trigger, CancellationToken cancellationToken = default); Task TriggerPaused (TriggerKey triggerKey, CancellationToken cancellationToken = default); Task TriggerResumed (TriggerKey triggerKey, CancellationToken cancellationToken = default) Task TriggersPaused (string triggerGroup, CancellationToken cancellationToken = default); Task TriggersResumed (string triggerGroup, CancellationToken cancellationToken = default);}

The code to add SchedulerListener is as follows:

Scheduler.ListenerManager.AddSchedulerListener (mySchedListener); persistence: JobStore

Quartz.Net supports the persistence operation of Job, which is called JobStore. By default, Quartz persists data into memory, the advantage is that the memory is fast, the disadvantage is that it cannot provide load balancing support, and after the program crashes, we will lose all Job data, for enterprise systems, the disadvantages obviously outweigh the benefits, so it is necessary to store the data in the database.

ADO.NET storage

Quartz uses ADO.NET to access databases and supports a wide range of database vendors:

SqlServer-SQL Server driver for .NET Framework 2.0

Oracle driver for OracleODP-Oracle

Oracle 11 managed driver for OracleODPManaged-Oracle

MySql-MySQL Connector / .NET

SQLite-SQLite ADO.NET Provider

SQLite-Microsoft-Microsoft SQLite ADO.NET Provider

Firebird-Firebird ADO.NET provider

Npgsql-PostgreSQL Npgsql

The database creation statement can be found in the source code of Quartz.Net: https://github.com/quartznet/quartznet/tree/master/database/tables

We can configure Quartz to use database storage through a configuration file:

# job storequartz.jobStore.type = Quartz.Impl.AdoJobStore.JobStoreTX, Quartzquartz.jobStore.dataSource = quartz_storequartz.jobStore.driverDelegateType = Quartz.Impl.AdoJobStore.PostgreSQLDelegate, Quartz#quartz.jobStore.useProperties = truequartz.dataSource.quartz_store.connectionString = Server=localhost;Database=quartz_store;userid=quartz_net;password=xxxxxx;Pooling=true;MinPoolSize=1;MaxPoolSize=10;Timeout=15;SslMode=Disable;quartz.dataSource.quartz_store.provider = Npgsql load balancer

Load balancing is a way to achieve high availability, when the task becomes larger, a single server is difficult to meet the needs, the use of load balancing makes the system has the ability to scale out, through the deployment of multiple nodes to increase the ability to deal with Job.

Quartz.Net relies on ADO JobStore when using load balancing, which means you need to use a database to persist data. Then we can use the following configuration to complete the load balancing function:

Quartz.jobStore.clustered = truequartz.scheduler.instanceId = AUTO

Clustered: identification of the cluster

InstanceId: the ID of the current Scheduler instance. The ID of each example cannot be repeated. When using AUTO, the system will automatically generate ID.

When we run an Scheduler instance on multiple servers, we need to set the server clock time to ensure that the server time is the same. For the windows server, you can set the automatic synchronization time from the network.

Access Quartz instances through Routing

The function of accessing Quartz instances through Routing provides a good way for us to do system separation.

We can achieve server-side remote access to Quartz through the following configuration:

# export this server to remoting contextquartz.scheduler.exporter.type = Quartz.Simpl.RemotingSchedulerExporter, Quartzquartz.scheduler.exporter.port = 555quartz.scheduler.exporter.bindName = QuartzSchedulerquartz.scheduler.exporter.channelType = tcpquartz.scheduler.exporter.channelName = httpQuartz

Then we configure access on the client system:

Quartz.scheduler.proxy = truequartz.scheduler.proxy.address = tcp://localhost:555/QuartzScheduler development practice

The ideal task scheduling system should be a background service, which runs silently in the background of the system, and the business system completes the operations of adding and deleting tasks through the interface. When building Windows services, you can integrate with TopShelf to complete the development of windows services.

Install-Package Topshelf

Another problem with service development is that Quartz itself does not support dependency injection, but to solve the problem of dependency injection, you can use Autofac. Fortunately, there are great gods who have completed the integration of TopShelf and Autofac, so we just need to use it.

Install-Package Topshelf.Autofac

There are two ways to add Quartz.Net Job: dynamically at run time and through configuration files. It is recommended to add dynamically (the sample code is added dynamically), unless your Job is relatively fixed.

The configuration of Scheduler can be done in the form of configuration files to facilitate maintenance during deployment.

At this point, I believe you have a deeper understanding of "what is the use of Quartz.Net?" you might as well do it in practice. Here is the website, more related content can enter the relevant channels to inquire, follow us, continue to learn!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report