当前位置:网站首页>Quartz uses the complete

Quartz uses the complete

2020-12-07 15:40:33 zzy0_0

http://www.quartz-scheduler.o...

1. Use Quartz

  • Quartz Scheduler Once closed , Can't restart

    • Re instantiation required
  • Provides pause status
SchedulerFactory schedFact = new org.quartz.impl.StdSchedulerFactory();

Scheduler sched = schedFact.getScheduler();

sched.start();

// define the job and tie it to our HelloJob class
JobDetail job = newJob(HelloJob.class)
  .withIdentity("myJob", "group1")
  .build();

// Trigger the job to run now, and then every 40 seconds
Trigger trigger = newTrigger()
  .withIdentity("myTrigger", "group1")
  .startNow()
  .withSchedule(simpleSchedule()
                .withIntervalInSeconds(40)
                .repeatForever())
  .build();

// Tell quartz to schedule the job using our trigger
sched.scheduleJob(job, trigger);

2.Quartz API,JOB and Trigger

http://www.quartz-scheduler.o...

  • JobBuilder- Used for definition / structure JobDetail example , This instance defines Jobs example .
  • JobDetail- Used for definition Job Example .
  • Job- The interface implemented by the component that you want to be executed by the scheduler .
  • TriggerBuilder- Used for definition / Instance building triggers .
  • Trigger- A component that defines the schedule on which a given job will be executed .

Scheduler

One Scheduler The life cycle is determined by the scope of its creation , adopt SchedulerFactory To call his create and close .

establish Scheduler after , You can use it

  • add to
  • Delete
  • List Job and Trigger

​ And perform other planning related operations ( For example, pause triggers ). however , The scheduler is using starter It wasn't really about anything before trigger Carrying out tasks works

Builder The presentation of

 // define the job and tie it to our HelloJob class
  JobDetail job = newJob(HelloJob.class)
      .withIdentity("myJob", "group1") // name "myJob", group "group1"
      .build();

  // Trigger the job to run now, and then every 40 seconds
  Trigger trigger = newTrigger()
      .withIdentity("myTrigger", "group1")
      .startNow()
      .withSchedule(simpleSchedule()
          .withIntervalInSeconds(40)
          .repeatForever())            
      .build();

  // Tell quartz to schedule the job using our trigger
  sched.scheduleJob(job, trigger);

Jobs and Triggers

Job It's an interface

public interface Job {

  public void execute(JobExecutionContext context)
    throws JobExecutionException;
}

When one Jobs When triggered to execute , Would call execute, In a Scheduler Of worker In the thread of .

JobExecutionContext It provides some variables needed when running

JobDetail stay Job Add to Scheduler When , It can contain some properties to set to job Of , for instance JobDataMap, He can let us store some status information for us Job

Trigger Used to trigger the execution of a task , Also includes JobDataMap, He can tell us when to carry out the mission . The default is SimpleTrigger and CronTrigger

SimpleTriggere

​ If you need to do it all at once ( Only one job is executed at a given time ), Or if you need to trigger a job at a given time , And let it repeat N Time , The delay between two executions is T, that SimpleTrigger Very convenient .

​ If you want a calendar like schedule ( For example, every Friday at noon or every month at the end of the month 10 Days of 10:15) Trigger , that CronTrigger Very useful .

Identifies

JobKey and TriggerKey

groups

3.Job and JobDetail Details of


  // define the job and tie it to our HelloJob class
  JobDetail job = newJob(HelloJob.class)
      .withIdentity("myJob", "group1") // name "myJob", group "group1"
      .build();

  // Trigger the job to run now, and then every 40 seconds
  Trigger trigger = newTrigger()
      .withIdentity("myTrigger", "group1")
      .startNow()
      .withSchedule(simpleSchedule()
          .withIntervalInSeconds(40)
          .repeatForever())            
      .build();

  // Tell quartz to schedule the job using our trigger
  sched.scheduleJob(job, trigger);
public class HelloJob implements Job {

  public HelloJob() {
  }

  public void execute(JobExecutionContext context)
    throws JobExecutionException
  {
    System.err.println("Hello!  HelloJob is executing.");
  }
}

Every time it's executed , Will call execute Create an instance of it before , After execution, it will be deleted and garbage collected .

  • requirement Job Implementation classes must have parameterless constructs
  • Job The state data fields defined above are useless , Because every time it's new , And it will be cleared

    • This kind of storage information is best used JobDataMap

JobDataMap

// define the job and tie it to our DumbJob class
JobDetail job = newJob(DumbJob.class)
  .withIdentity("myJob", "group1") // name "myJob", group "group1"
  .usingJobData("jobSays", "Hello World!")
  .usingJobData("myFloatValue", 3.141f)
  .build();
public class DumbJob implements Job {

    public DumbJob() {
    }

    public void execute(JobExecutionContext context)
      throws JobExecutionException
    {
      JobKey key = context.getJobDetail().getKey();

      JobDataMap dataMap = context.getJobDetail().getJobDataMap();

      String jobSays = dataMap.getString("jobSays");
      float myFloatValue = dataMap.getFloat("myFloatValue");

      System.err.println("Instance " + key + " of DumbJob says: " + jobSays + ", and val is: " + myFloatValue);
    }
  }
  • Stored objects are serialized , We need to pay attention to the version problem
  • If keyName Corresponding to set+Keyname Then the corresponding Job Of setter Method

JobExecutionContext Can help us merge Trigger and JobDetail Upper JobDataMap The value of the inside ,Trigger Upper key Will be covered JobDetail Upper


public class DumbJob implements Job {

  public DumbJob() {
  }

  public void execute(JobExecutionContext context)
    throws JobExecutionException
  {
    JobKey key = context.getJobDetail().getKey();

    JobDataMap dataMap = context.getMergedJobDataMap();  // Note the difference from the previous example

    String jobSays = dataMap.getString("jobSays");
    float myFloatValue = dataMap.getFloat("myFloatValue");
    ArrayList state = (ArrayList)dataMap.get("myStateData");
    state.add(new Date());

    System.err.println("Instance " + key + " of DumbJob says: " + jobSays + ", and val is: " + myFloatValue);
  }
}

Job example

Trigger trigger , It will load the corresponding JobDetail, And through the configuration of Jobfactory To instantiate the corresponding Job

image-20201207112924692

And try to match it with JobFactory Call and JobDataMap The key name in the setter Method .

Working state and concurrent execution

@DisallowConcurrentExecution

This is used to add to Job Class above , To tell Quartz Don't do the same thing at the same time Job

@PersistJobDataAfterExecution

Also add to Job Class above , tell Quartz After execution ( No exception occurred ), to update JobDataMap The storage , It is used to tell you that the current set value can be obtained at the next execution .

other

  • persistence

    • If Job It won't be used any more , Automatically from Scheduler Delete , This and Trigger relevant
RequestsRecovery - if a job “requests recovery”, and it is executing during the time of a ‘hard shutdown’ of the scheduler (i.e. the process it is running within crashes, or the machine is shut off), then it is re-executed when the scheduler is started again. In this case, the JobExecutionContext.isRecovering() method will return true.

4. About Trigger

​ image Job equally ,Trigger It's also easy to use , But it does include a variety of custom options , Make full use of Quartz Before , You need to understand them and understand them . Again , As mentioned earlier , You can choose different types of Trigger To meet different scheduling needs .

General purpose Trigger attribute

  • JobKey:

    • When the trigger is executed job identification
  • startTime: Identify the trigger effective time
  • endTime: Trigger end time

priority

When we trigger a lot ,Quartz When there are few worker threads in the thread pool , There may not be enough resources for colleagues to start all triggers to be triggered , If no priority is specified , Will use the default priority 5

Priority configuration supports any integer value Positive or negative numbers

Be careful : Only when the trigger time is the same, the priority will be compared , Plan in 10:59 The trigger triggered will always be planned in 11:00 Trigger before trigger .

Be careful : When a job that detects a trigger needs to be restored , Its recovery is scheduled to have the same priority as the original trigger .

CronTrigger trigger = TriggerBuilder.newTrigger().
  withIdentity(getTriggerKey(scheduleJobEntity.getId())).
  withSchedule(cronScheduleBuilder).
  startAt(scheduleJobEntity.getStartTime()).
  endAt(scheduleJobEntity.getEndTime()).
  withPriority(10).
  build();

The calendar

​ Calendars are useful for excluding time periods from trigger schedules for triggers . for example , You can create a trigger , The trigger is on the morning of every working day 9:30 Trigger a job , Then add a calendar that excludes all corporate holidays .

public interface Calendar {

  public boolean isTimeIncluded(long timeStamp);

  public long getNextIncludedTime(long timeStamp);

}

All the above interfaces are milliseconds , For convenience Quartz It also provides HolidayCalendar To provide full day exclusion

HolidayCalendar cal = new HolidayCalendar();
cal.addExcludedDate( someDate );
cal.addExcludedDate( someOtherDate );

sched.addCalendar("myHolidays", cal, false);


Trigger t = newTrigger()
  .withIdentity("myTrigger")
  .forJob("myJob")
  .withSchedule(dailyAtHourAndMinute(9, 30)) // execute job daily at 9:30
  .modifiedByCalendar("myHolidays") // but not on holidays
  .build();

// .. schedule job with trigger

Trigger t2 = newTrigger()
  .withIdentity("myTrigger2")
  .forJob("myJob2")
  .withSchedule(dailyAtHourAndMinute(11, 30)) // execute job daily at 11:30
  .modifiedByCalendar("myHolidays") // but not on holidays
  .build();

// .. schedule job with trigger2

5.SimpleTrigger

​ If you need to perform a job exactly at a specific time or at a specific time , And then repeat it at a specific interval , SimpleTrigger Should be able to meet your scheduling needs . for example , If you want the trigger to be in 2015 year 1 month 13 The morning of 11:23:54 Trigger , Or you want to trigger , And then five times every ten seconds .

  • attribute

    • Start time and end time
    • Repeat count

      • It can be zero , Positive integer , Constant values SimpleTrigger.REPEAT_INDEFINITELY
    • Repeat interval

      • Must be zero or positive , Represents the number of milliseconds
      • The interval is 0

DateBuilder Class helps to calculate the trigger time of a trigger , It depends on our start and end times

Priority and repeat count are greater than start time

Set up triggers for a specific time , Don't repeat

import static org.quartz.TriggerBuilder.*;
import static org.quartz.SimpleScheduleBuilder.*;
import static org.quartz.DateBuilder.*:

SimpleTrigger trigger = (SimpleTrigger) newTrigger()
  .withIdentity("trigger1", "group1")
  .startAt(myStartTime) // some Date
  .forJob("job1", "group1") // identify job with name, group strings
  .build();

Set up triggers for a specific time , Repeat ten times every ten seconds

trigger = newTrigger()
  .withIdentity("trigger3", "group1")
  .startAt(myTimeToStartFiring)  // if a start time is not given (if this line were omitted), "now" is implied
  .withSchedule(simpleSchedule()
                .withIntervalInSeconds(10)
                .withRepeatCount(10)) // note that 10 repeats will give a total of 11 firings
  .forJob(myJob) // identify job with handle to its JobDetail itself                   
  .build();

Create a trigger , The trigger will trigger once in the next five minutes

trigger = (SimpleTrigger) newTrigger()
  .withIdentity("trigger5", "group1")
  .startAt(futureDate(5, IntervalUnit.MINUTE)) // use DateBuilder to create a date in the future
  .forJob(myJobKey) // identify job with its JobKey
  .build();

Create a trigger that will now trigger , And then repeat it every five minutes , until 22:00

trigger = newTrigger()
  .withIdentity("trigger7", "group1")
  .withSchedule(simpleSchedule()
                .withIntervalInMinutes(5)
                .repeatForever())
  .endAt(dateOf(22, 0, 0))
  .build();

Create a trigger , The trigger will trigger at the top of the next hour , And then forever every 2 Repeat once every hour :


  trigger = newTrigger()
    .withIdentity("trigger8") // because group is not specified, "trigger8" will be in the default group
    .startAt(evenHourDate(null)) // get the next even-hour (minutes and seconds zero ("00:00"))
    .withSchedule(simpleSchedule()
        .withIntervalInHours(2)
        .repeatForever())
    // note that in this example, 'forJob(..)' is not called
    //  - which is valid if the trigger is passed to the scheduler along with the job  
    .build();

    scheduler.scheduleJob(trigger, job);

SimpleTrigger MisFire

MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY
MISFIRE_INSTRUCTION_FIRE_NOW
MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT
MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_REMAINING_REPEAT_COUNT
MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT
MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_EXISTING_COUNT

6.CronTrigger

​ If you need a concept based on something similar to a calendar, not based on SimpleTrigger The exact time interval between layoffs , be CronTrigger Often than SimpleTrigger Useful .

​ Use CronTrigger, You can specify a trigger plan , for example “ Every Friday at noon ”,“ Every working day to 9:30”, even to the extent that “ Every Monday , On Wednesday morning 9:00 to 10:00 Between each 5 minute ” And Friday in January ”.

​ even so , And SimpleTrigger equally ,CronTrigger Has a startTime, Used to specify when the plan will take effect ; And one. ( Optional )endTime, Used to specify when a plan ends .

Cron expression

http://www.quartz-scheduler.o...

Expressions are used to configure CronTrigger Example .Cron-Expression Is actually a string of seven subexpressions , They describe the details of the schedule . These subexpressions are separated by spaces , representative :

  1. second
  2. minute
  3. Hours
  4. Some day of the month
  5. month
  6. What day
  7. year ( Optional fields )
  • ​ complete cron An example of an expression is a string 0 0 12 ?* WED

    • For every Wednesday 12:00:00 pm”.

Each subexpression can contain ranges and / Or list .

  • for example , the previous WED The field can be replaced with “ MON-FRI”,“ MON,WED,FRI”, even to the extent that “ MON-WED,SAT”.

wildcard '' Can be used to represent all possible values of a field

* For every day of the week

/ Represents the increment of the specified value .

  • For example, in the minutes field 0/15, It means every hour 15 minute , from 0 minutes ,
  • If you use 3/20 Means the... Of every hour 20 minute , Three minutes from the ground
  • <span style='color:red'> Be careful </span>:/35 It doesn't mean every 35 minute , It's every... Every hour 35 minute , From zero minutes 0/35

?: The day of the week and the day of the week fields allow the characters . Is used to specify the “ There is no specific value ”. When you need to specify an item in one of the two fields instead of the other , It's very useful

L: For months and weeks , For the last , Month means the last day of the month 1 month 31 Japan ,2 month 28 Japan . A word used for a week means 7 perhaps sat( Saturday ), If 6L Represents the last Friday of the month , Can be used to specify the offset for the last day of the month L-3, It means the penultimate day of a calendar month

W A working day used to specify a given date ( Monday to Friday ),15W It means to leave every month 15 The most recent working day

For the specified month “ n” individual XXX Working day . for example , What day In the field 6#3 or FRI#3 The value of represents The third Friday of every month .

Cron Examples of expressions

CronTrigger Example 1- Used to create only every 5 One minute trigger of the expression

 0 0/5 * * *?

CronTrigger Example 2- Create an expression for a trigger , The trigger every 5 Minutes to trigger , After every minute 10 second ( for example 10:00:10 am,10:05:10 am etc. ) Trigger .

 10 0/5 * * * ?

CronTrigger Example 3- Create an expression for a trigger , The trigger is on every Wednesday and Friday 10:30、11:30、12:30 and 13:30 Trigger .

 0 30 10-13 ?* WED,FRI

CronTrigger Example 4- Create an expression for a trigger , The trigger is on the 5 Number and 20 On the morning of the th 8 Point to 10 Trigger every half an hour between points . Please note that , Triggers don't happen in the morning 10:00, Only in 8:00、8:30、9:00 and 9:30 Trigger

0 0/30 8-9 5,20 * ?

Please note that , Some planning requirements are too complex to be expressed in a single trigger , for example “ In the morning 9:00 To the morning 10:00 Between each 5 Minutes at a time , Afternoon 1:00 to 10:00 Every afternoon 20 Minutes at a time ”. The solution in this case is to simply create two triggers , And register two triggers to run the same job .

structure CronTriggers

import static org.quartz.TriggerBuilder.*;
import static org.quartz.CronScheduleBuilder.*;
import static org.quartz.DateBuilder.*:

Create a trigger , The trigger every day from the morning 8 Point to the afternoon 5 Trigger every other minute between the dots :

trigger = newTrigger()
  .withIdentity("trigger3", "group1")
  .withSchedule(cronSchedule("0 0/2 8-17 * * ?"))
  .forJob("myJob", "group1")
  .build();

Set up triggers , Every day 10:42 am Trigger

trigger = newTrigger()
  .withIdentity("trigger3", "group1")
  .withSchedule(dailyAtHourAndMinute(10, 42))
  .forJob(myJobKey)
  .build();

perhaps

trigger = newTrigger()
  .withIdentity("trigger3", "group1")
  .withSchedule(cronSchedule("0 42 10 * * ?"))
  .forJob(myJobKey)
  .build();

Build a trigger , The trigger will be on Wednesday morning 10:42, Use other than the system default value TimeZone Trigger

trigger = newTrigger()
  .withIdentity("trigger3", "group1")
  .withSchedule(weeklyOnDayAndHourAndMinute(DateBuilder.WEDNESDAY, 10, 42))
  .forJob(myJobKey)
  .inTimeZone(TimeZone.getTimeZone("America/Los_Angeles"))
  .build();

perhaps

 trigger = newTrigger()
    .withIdentity("trigger3", "group1")
    .withSchedule(cronSchedule("0 42 10 ? * WED"))
    .inTimeZone(TimeZone.getTimeZone("America/Los_Angeles"))
    .forJob(myJobKey)
    .build();

CronTrigger MisFire explain

MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY
MISFIRE_INSTRUCTION_DO_NOTHING
MISFIRE_INSTRUCTION_FIRE_NOW
 trigger = newTrigger()
    .withIdentity("trigger3", "group1")
    .withSchedule(cronSchedule("0 0/2 8-17 * * ?")
        ..withMisfireHandlingInstructionFireAndProceed())
    .forJob("myJob", "group1")
    .build();

7.TriggerListeners and JobListeners

​ Listeners are objects that you create , Used to perform actions based on events that occur in the scheduler . You may have guessed ,TriggerListeners* Receives events related to the trigger , and JobListeners* Receive events related to the job .

public interface TriggerListener {

  public String getName();

  public void triggerFired(Trigger trigger, JobExecutionContext context);

  public boolean vetoJobExecution(Trigger trigger, JobExecutionContext context);

  public void triggerMisfired(Trigger trigger);

  public void triggerComplete(Trigger trigger, JobExecutionContext context,
                              int triggerInstructionCode);
}

Events related to the job include : Notification that the job is about to be performed , And notification when the job is completed .

public interface JobListener {

  public String getName();

  public void jobToBeExecuted(JobExecutionContext context);

  public void jobExecutionVetoed(JobExecutionContext context);

  public void jobWasExecuted(JobExecutionContext context,
                             JobExecutionException jobException);

}

Use your own listener

​ You want to create a listener , Just create an implementation org.quartz.TriggerListener or org.quartz.JobListener Object of the interface . then , Register the listener with the scheduler at run time , And you have to give it a name ( Or say , They have to go through their getName() Publish your own method name ).

​ Listener and scheduler ListenerManager Sign up with , The Matcher Describes the job for which the listener will receive events / trigger .

The listener registers with the scheduler at run time , And it's not stored with jobs and triggers in JobStore in . This is because listeners are usually the integration point for your application . therefore , Every time your application runs , You need to re register the listener in the scheduler .
scheduler.getListenerManager().addJobListener(myJobListener, jobKeyEquals(jobKey("myJobName", "myJobGroup")));

Add interested in all jobs for a specific group JobListener

scheduler.getListenerManager().addJobListener(myJobListener, jobGroupEquals("myJobGroup"));

Add... That is interested in all jobs for two specific groups JobListener

scheduler.getListenerManager().addJobListener(myJobListener, or(jobGroupEquals("myJobGroup"), jobGroupEquals("yourGroup")));

Add... Interested in all assignments JobListener

scheduler.getListenerManager().addJobListener(myJobListener, allJobs());

​ Quartz Most of our users don't use listeners , But when an application needs to create a requirement for event notification , Listeners are very handy , and Job There is no need to explicitly notify the application itself .

8.SchedulerListeners

*SchedulerListener* And TriggerListeners and JobListeners Very similar , Except they're in Scheduler Receive notification of events within itself - Events that are not necessarily related to a particular trigger or job .

Events related to the scheduler include : Add the homework / trigger , Remove the job / trigger , A serious error in the scheduler , Notify the scheduler that it is shutting down, etc .

public interface SchedulerListener {

  public void jobScheduled(Trigger trigger);

  public void jobUnscheduled(String triggerName, String triggerGroup);

  public void triggerFinalized(Trigger trigger);

  public void triggersPaused(String triggerName, String triggerGroup);

  public void triggersResumed(String triggerName, String triggerGroup);

  public void jobsPaused(String jobName, String jobGroup);

  public void jobsResumed(String jobName, String jobGroup);

  public void schedulerError(String msg, SchedulerException cause);

  public void schedulerStarted();

  public void schedulerInStandbyMode();

  public void schedulerShutdown();

  public void schedulingDataCleared();
}

Add one SchedulerListener

scheduler.getListenerManager().addSchedulerListener(mySchedListener);

Delete SchedulerListener

scheduler.getListenerManager().removeSchedulerListener(mySchedListener);

9.JobStore

​ JobStore Responsible for tracking all of the “JobData”: Homework , trigger , Calendar, etc . by Quartz The scheduler instance selects the appropriate JobStore It's an important step .

​ Fortunately, , Once you understand the difference between the two , So it's very easy to choose .

​ You are providing SchedulerFactory Property file of ( Or object ) State which scheduler should use JobStore( And its configuration Settings ).

Do not use it directly in code JobStore example . For some reason , Many people try to do this .JobStore be used for Quartz Itself behind the scenes . You must ( By configuring ) tell Quartz Which one to use JobStore, But you should only use... In your code Scheduler Interface .

RAMJobStore

​ RAMJobStore It's the easiest to use JobStore, It's also the highest performance ( Just CPU In terms of time ).RAMJobStore It's obvious that :

  • Keep all data in RAM in . That's why it's lightning fast , And that's why it's so simple to configure .
  • The disadvantage is that

    • When your application is finished ( Or crash ) when , All scheduling information will be lost -
    • It means RAMJobStore unacceptable Job and Trigger Upper duriable Set up .
    • For some applications , This is acceptable , Even the required behavior , But for other applications , This could be catastrophic .

To use RAMJobStore( And suppose you're using StdSchedulerFactory), Just put the class name org.quartz.simpl.RAMJobStore Designated for configuration of quartz JobStore Class properties :

org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore

JDBCJobStore

image-20201207144438495

​ JDBCJobStore It's also properly named - It passes through JDBC Save all its data in the database . therefore , Its configuration is better than RAMJobStore More complicated , And it's not that fast .

​ however , Performance degradation is not so bad , Especially when you use the index on the primary key to build a database table . In having proper LAN( Between the scheduler and the database ) On a fairly modern set of computers , Retrieving and updating the trigger time is usually Less than 10 millisecond .

​ JDBCJobStore It can be used with almost any database , It has been Oracle,PostgreSQL,MySQL,MS SQLServer,HSQLDB and DB2 Widely used . To use JDBCJobStore, You must first create a set of database tables for Quartz Use . You can go to Quartz Distribution docs / dbTables Find the table in the directory to create SQL Script . If there is no script for your database type , Just look at one of the existing scripts , Then modify it in any way that the database needs . One thing to pay attention to is , In these scripts , All tables are prefixed “ QRTZ_” start ( Such as table “ QRTZ_TRIGGERS” and “ QRTZ_JOB_DETAIL”). As long as you tell me JDBCJobStore What is the prefix ( stay Quartz Properties of the ), The prefix can actually be any prefix you want . Using different prefixes for creating multiple table sets , Multiple instances of the scheduler can be useful ,

​ After creating the table , In configuration and startup JDBCJobStore Before , You need to make another important decision . You need to determine what things your application needs to manage . If you don't need to schedule the command ( For example, adding and deleting triggers ) Binding to other transactions , Then you can make Quartz By way of JobStoreTX Used as a JobStore To manage things ( This is the most common choice ).

​ If you need Quartz Work with other things ( That is to say J2EE Application server ), You should use JobStoreCMT- under these circumstances ,Quartz Will allow the application server container to manage transactions .

The last problem is to set up a data source ,JDBCJobStore A connection to your database can be obtained from this data source .

​ Data sources are used in one of several different ways in Quartz Property .

  • ​ One way is to let Quartz Create and manage by providing all connection information to the database DataSource In itself .
  • Another way is by offering JDBCJobStore Data sources JNDI name , send Quartz Use by Quartz The application server running in it manages the data source . More about properties , Please refer to docs / config Sample configuration file in folder .

To use JDBCJobStore( And suppose you use StdSchedulerFactory), First, you need to Quartz Configured JobStore The class property is set to org.quartz.impl.jdbcjobstore.JobStoreTX or org.quartz.impl.jdbcjobstore.JobStoreCMT Choose according to the instructions in the paragraphs above .

To configure Quartz To use the JobStoreTx

org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX

​ Next , You need to choose one DriverDelegate for JobStore Use .DriverDelegate Responsible for any... That may be required to complete a specific database JDBC Work .

​ StdJDBCDelegate It's using “ original ” JDBC Code ( and SQL sentence ) A commission to complete its work . If there is no other delegate created specifically for your database , Try using this delegate - We only use StdJDBCDelegate And ( Found the most !) The database that found the problem has a database specific delegation . Other representatives can be in “ org.quartz.impl.jdbcjobstore” Found in a package or its subpackages . Other representatives include DB2v6Delegate( be used for DB2 edition 6 And earlier ),HSQLDBDelegate( be used for HSQLDB),MSSQLDelegate( be used for Microsoft SQLServer),PostgreSQLDelegate( be used for PostgreSQL),WeblogicDelegate( Used to use by Weblogic Made of JDBC The driver ),

After selecting the delegation , Set its class name to JDBCJobStore Delegation used .

To configure JDBCJobStore To use the DriverDelegate

org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate

Next , You need notification JobStore The table prefix you are using ( As discussed above ).

Use the table prefix to configure JDBCJobStore

org.quartz.jobStore.tablePrefix = QRTZ_

​ Last , You need to set JobStore Which data source should be used . Must also be in Quartz Property to define named DataSource. under these circumstances , We specify Quartz The data source name should be used “ myDS”( Define... Elsewhere in the configuration properties ).

Configure with the name of the data source to be used JDBCJobStore

org.quartz.jobStore.dataSource = myDS
If your scheduler is busy ( That is, it almost always executes the same number of jobs as the thread pool size ), Then maybe you should DataSource The number of connections in is set to the size of the thread pool + 2.

Can be “ org.quartz.jobStore.useProperty” The configuration parameter is set to “ true”( The default is false), To indicate that JDBCJobStore JobDataMaps All values in are strings , So it can be stored as a name - It's worth it , Instead of storing more complex objects in their serialization form in BLOB In the column . In the long run , It's safer to do this , Because it can avoid the possibility of String Class is serialized to BLOB The problem of class version control appears when .

TerracottaJobStore

​ TerracottaJobStore Provides a way to scale and enhance functionality without using a database . This means that your database is free from Quartz The load of , You can save all the resources for the rest of the application .

​ TerracottaJobStore It can be clustered or non clustered , And in both cases, it can provide a storage medium for your job data , This storage medium is persistent between application restarts , Because the data is stored in Terracotta Server . Its performance ratio is JDBCJobStore It's much better to use a database ( About an order of magnitude ), But more than RAMJobStore Much slower .

​ To use TerracottaJobStore( And suppose you use StdSchedulerFactory), Just specify the class name org.quartz.jobStore.class = org.terracotta.quartz.TerracottaJobStore As used to configure Quartz Of JobStore Class properties , Then add a line of configuration to specify Terracotta Location of the server :

org.quartz.jobStore.class = org.terracotta.quartz.TerracottaJobStore
org.quartz.jobStore.tcConfigUrl = localhost:9510

About this JobStore and Terracotta For more information , Please visit http://www.terracotta.org/quartz.

10. To configure , Resource usage and SchedulerFactory

Quartz The architecture of is modular , So make it work , You need to put multiple components “ binding ” together . Fortunately, , There are some helpers to help achieve this goal .

Quartz The main components that need to be configured before work is :

  • Thread pool
  • Job Library
  • data source
  • Scheduler itself

The * Thread pool * Provides a set of threads for Quartz In execution Jobs When using . The more threads in the pool , The more jobs you can run in parallel . however , Too many threads can paralyze your system .

​ majority Quartz Users find 5 There are enough threads - Because at any given time they are less than 100 Homework , These jobs are not usually scheduled to run at the same time , And these assignments are short-lived ( Finish quickly ).

​ Other users find that they need 10、15、50 even to the extent that 100 Threads - Because they have thousands of triggers with various plans - In the end, on average 10 To 100 Jobs that try to execute at any given time .

​ Finding the right size for the scheduler pool depends entirely on what you are using the scheduler for . There are no real rules , In addition to keeping the number of threads as small as possible ( In order to save computer resources ) Outside - Also make sure there is enough space to start the job on time .

​ Please note that , If the trigger time is up , And there are no threads available ,Quartz Will block ( Pause ) Until a thread is available , Then the job will execute - A few milliseconds behind the original time .

​ If the scheduler is configured with misfire threshold There are no threads available during , This may even cause the thread not to trigger .

​ stay org.quartz.spi It's defined in the package ThreadPool Interface , You can create it any way you like ThreadPool Realization .Quartz It comes with a simple ( But it's very satisfying ) Thread pool of , be known as org.quartz.simpl.SimpleThreadPool. this ThreadPool Just maintain a fixed set of threads in its pool - Never grow , Never shrink . But it's very robust , And it's been well tested - Because almost all use Quartz People who use the pool .

​ It's worth mentioning here , all JobStore It's all done org.quartz.spi.JobStore Interface - If it's bound JobStore One does not meet your needs , Then you can make it yourself .

​ Last , You need to create Scheduler example . Need to give Scheduler It's a name , Tell it RMI Set up , And transmission JobStore and ThreadPool Example .RMI Settings include whether the scheduler should create itself as RMI Server object for ( Make it available for remote connections ), Host and port to be used, etc .StdSchedulerFactory( Let's talk about ) It can also produce what is actually a proxy Scheduler example ( RMI stub ) To a scheduler created in a remote process .

StdSchedulerFactory

​ StdSchedulerFactory yes org.quartz.SchedulerFactory Interface implementation . It USES a set of properties (java.util.Properties) Create and initialize Quartz Scheduler.

​ These properties are typically stored in a file and loaded from the file , But it can also be created by the program and delivered directly to the factory . Just call... On the factory getScheduler() To generate a scheduler , Initialize it ( And its ThreadPool,JobStore and DataSources), And return the handle to its public interface .

Quartz Distribution “ docs / config” There are some sample configurations in the directory ( Include attribute descriptions ). You can go to Quartz Document “Reference” Part of the “Configuration” The complete documentation is found in the manual .

DirectSchedulerFactory

DirectSchedulerFactory Is another SchedulerFactory Realization . For those who want to create it in a more programmatic way Scheduler For instance users , It's very useful . It is generally not recommended to use it , Here's why :

  • It requires users to have a deeper understanding of their work
  • It does not allow declarative configuration - let me put it another way , It's going to be hard for you to - Encode all scheduler settings .

journal

Quartz Use SLF4J Framework to meet all its logging needs . in order to “ adjustment ” Logging settings ( For example, the number of outputs and the location of outputs ), You need to understand SLF4J frame , This is outside the scope of this document .

If you want to capture additional information about trigger firing and job execution , It is possible to enable org.quartz.plugins.history.LoggingJobHistoryPlugin or org.quartz.plugins.history.LoggingTriggerHistoryPlugin Interested in .

11. Advanced features

​ The cluster can currently work with JDBC-Jobstore(JobStoreTX or JobStoreCMT) and TerracottaJobStore Use it together . Features include load balancing and job failover ( If JobDetail Of “ Request to restore ” Flag set to true).

Use JobStoreTX or JobStoreCMT Cluster by putting org.quartz.jobStore.isClustered Property is set to “ true” To enable the cluster .

​ Every instance in the cluster should use quartz.properties Same copy of file . The exception is to use the same properties file , But the following exceptions are allowed : Different thread pool sizes and org.quartz.scheduler.instanceId Different values for attributes .

​ Each node in the cluster must have a unique instanceId, It can be done by putting “ AUTO” Place as the value of the property to easily complete ( No other property files are required ).

Do not run a cluster on a separate computer , Unless you use some form of time synchronization service that runs very regularly ( A daemon ) Synchronize their clocks ( The time interval between clocks must be between 1 Within seconds, ). If you are not familiar with this operation , see also http://www.boulder.nist.gov/t....

Do not start a non clustered instance against the same set of tables that other instances are running . You may experience severe data corruption , And there's bound to be unstable behavior

​ Every time it's triggered , Only one node will trigger the job . Well, I mean , If the job has duplicate triggers , Tell it every time 10 Second trigger once , It's in 12:00:00 Just one node will run the job , And in the 12:00:10 Just one node will run jobs and so on . It doesn't have to be on the same node every time - Which node runs it is more or less random . For busy schedulers ( Lots of triggers ), The load balancing mechanism is almost random , But for non busy schedulers ( for example , One or two triggers ) Only the same node that is active .

Use TerracottaJobStore To cluster, you only need to configure the scheduler to use TerracottaJobStore( Already in The first 9 course :JobStores Described in the ), Your scheduler will all be set up as a cluster .

​ You may also need to consider how to set up Terracotta What the server means , In particular, turn on features such as persistence and for HA Run a series of Terracotta Server configuration options .

​ TerracottaJobStore Enterprise Edition offers advanced Quartz Where function , Jobs can be intelligently directed to the appropriate cluster nodes .

JTA thing

JobStoreCMT Allow in larger JTA To execute in a transaction Quartz Scheduling operations .

​ By way of org.quartz.scheduler.wrapJobExecutionInUserTransaction Property is set to true, Homework can also be done in JTA Business (UserTransaction) In the implementation of .

​ After setting this option ,JTA Business will be in Job Of execute Before the method is called begin(), and execute After the call is terminated commit(). This applies to all assignments .

​ If you want to indicate for each assignment JTA Whether a transaction should wrap its execution , You should use @ExecuteInJTATransaction Comments .

​ except Quartz stay JTA Automatic wrapping in transactions Job Beyond execution , In the use of JobStoreCMT when , You are in Scheduler Calls made on the interface also participate in the transaction . Just make sure that the transaction is started , Then call the method on the scheduler . You can use the UserTransaction To do this directly , You can also put the code that uses the scheduler in a container managed transaction SessionBean in .

12. Other features

​ Quartz Provides an interface for inserting additional functions (org.quartz.spi.SchedulerPlugin).

​ Can be in *org.quartz.plugins* Found in the package Quartz Plug ins that provide various utility functions are included . They provide some functions , For example, automatically schedule jobs when the scheduler starts , Record the history of jobs and trigger events , And to ensure that the JVM On exit, the scheduler closes completely .

JobFactory

​ When the trigger is triggered , Will pass at Scheduler The configuration of JobFactory Instantiate the associated Job. default JobFactory Call only on the job class newInstance().

​ You may need to create your own JobFactory Realization , To complete, for example, the application's IoC or DI Container to generate / Initialize a job instance or something like that .

Factory-Shipped Jobs

​ Quartz There are also many utility jobs available , You can use them in your application to do things like send email and call EJB Things like that . These out of the box assignments can be found in *org.quartz.jobs* Found in the package .

版权声明
本文为[zzy0_0]所创,转载请带上原文链接,感谢
https://chowdera.com/2020/12/20201207154001360r.html