Quartz 技术开发文档

1. 如何实现Quartz远程控制;

    (1) 通过数据库实现远程quartz的控制:

        服务端(任务的执行端)例如 quartz_jobs.jar 通过 java -jar quartz_jobs.jar 执行任务;

       (一) 创建quartz 数据库 并创建quartz的表(sql由官方提供) 下载 quartz-2.2.2-distribution.tar 包 解压后 \quartz-2.2.2\docs\dbTables 文件下(这里以MySQL为例)

创建 quartz任务存储的数据库这里叫 crawl_quartz 
并将 tables_mysql_innodb.sql 导入数据库中

       (二) 在项目的根目录下 src 下添加 quartz.properties 文件 有关配置参看官方文档:https://www.quartz-scheduler.org/generated/2.2.2/html/qtz-all/#page/quartz-scheduler-webhelp%2F_qs_all.1.041.html%23 

#==============================================================    
#Configure Main Scheduler Properties    
#==============================================================     
org.quartz.scheduler.instanceName = v1_crawl_scheduler  
org.quartz.scheduler.instanceId = AUTO  

#==============================================================    
#Configure JobStore (配置quartz 任务的存储方式 : 包括 数据库存储 和 内存存储)   
#==============================================================  
# 以下为数据库的存储并需要配置数据库
org.quartz.scheduler.instanceName = v1_crawl_scheduler
org.quartz.threadPool.threadCount = 3
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.tablePrefix = QRTZ_
org.quartz.jobStore.dataSource = v1_dataSource
org.quartz.jobStore.isClustered = true  
org.quartz.jobStore.clusterCheckinInterval = 20000  

# 本地内存存储(不需要配置数据库)
#org.quartz.jobStore.misfireThreshold = 60000  
#org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore  

#==============================================================    
#Configure DataSource    (指定quartz 数据库 并配置 就是第一步说的那个数据库)
#============================================================== 
org.quartz.dataSource.v1_dataSource.driver = com.mysql.jdbc.Driver
org.quartz.dataSource.v1_dataSource.URL = jdbc:mysql://192.168.5.8:3306/crawl_quartz?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull
org.quartz.dataSource.v1_dataSource.user = test
org.quartz.dataSource.v1_dataSource.password = test
org.quartz.dataSource.v1_dataSource.maxConnections = 20

#==============================================================    
#Configure ThreadPool   (quartz 的线程控制) 
#==============================================================   
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool  
org.quartz.threadPool.threadCount = 10  
org.quartz.threadPool.threadPriority = 5  
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true

         控制端实现  (调用里面的方法,会自动修改配置数据中的数据)

package org.crawl.quartz;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import org.apache.log4j.Logger;
import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobBuilder;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.SimpleTrigger;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.quartz.Trigger.TriggerState;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.impl.matchers.GroupMatcher;

import cn.v1.video.crawl.task.CarwlJob;

/**
 * 定时任务管理器
 * @author hp
 *
 */
public class SchedulerFactoryManager  {
	private static final Logger logger=Logger.getLogger(SchedulerFactoryManager.class);
	
	private final static SchedulerFactory schedulerFactory = new StdSchedulerFactory();
	//单例(构造方法私有化)
	private SchedulerFactoryManager(){};
	
	//获取Scheduler 对象
	private static Scheduler getScheduler() throws SchedulerException{
		return schedulerFactory.getScheduler();
	}
	
	//关闭定时器
	public static void shutdown(){
		try {
			Scheduler scheduler=getScheduler();
			if(scheduler.isStarted()){
				scheduler.shutdown();
				logger.info("---关闭当前的定时器---");
			}
		} catch (SchedulerException e) {
			logger.error("关闭定时器异常", e);
		}
		
	}
	
	//启动定时器
	public static void start(){
		try {
			Scheduler scheduler= getScheduler();
			if(scheduler.isShutdown()){
				scheduler.start();
				 logger.info("---启动定时器---");
			}
		} catch (SchedulerException e) {
			logger.error("启动定时器异常", e);
		}
		
	}
	/**
	 * 暂停任务
	 */
	public static boolean pauseJob(Integer taskId,Integer groupId){
			boolean flag=false;
		try {
			 Scheduler scheduler=getScheduler();
			 JobKey jobKey= JobKey.jobKey(String.valueOf("task_"+taskId),"group_"+groupId);
			 scheduler.pauseJob(jobKey); //暂停任务
			 logger.info("----暂停任务---"+"task_"+taskId+",group_"+taskId+"--------");
			 flag=true;
		} catch (SchedulerException e) {
			logger.error("---暂停任务异常---", e);
		}
		return flag;
	}
	
	/**
	 * 恢复任务
	 * @param taskId
	 * @param groupId
	 * @return
	 */
	public static boolean resumeJob(Integer taskId,Integer groupId){
			boolean flag=false;
		try {
			Scheduler scheduler=getScheduler();
			JobKey jobKey= JobKey.jobKey(String.valueOf("task_"+taskId),"group_"+groupId);
			scheduler.resumeJob(jobKey);
			flag=true;
		} catch (SchedulerException e) {
			logger.error("---恢复任务异常---", e);
		}
		return flag;
	}
	
	
	/**
	 * 删除任务
	 * @param taskId
	 * @param groupId
	 * @return
	 */
	public static boolean delJob(Integer taskId,Integer groupId){
			boolean flag=false;
		try {
			Scheduler scheduler=getScheduler();
			JobKey jobKey= JobKey.jobKey(String.valueOf("task_"+taskId),"group_"+groupId);
			scheduler.deleteJob(jobKey);
			flag=true;
		} catch (SchedulerException e) {
			logger.error("---恢复任务异常---", e);
		}
		return flag;
	}
	
	//添加测试任务并立即执行(只执行一次)
	public static  boolean addTestJob(Integer taskId,Integer groupId,String taskName,final Map<String, Object> jobMap){
		TestScheduler testScheduler=new TestScheduler();
		return testScheduler.execTestJob(taskId, groupId, taskName, jobMap);
	}
	/**
	 * 删除所有的任务
	 * @return
	 */
	public static boolean delAllJobs(){
		boolean flag=false;
		try {
			Scheduler scheduler=getScheduler();
			GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup(); 
			Set<JobKey> jobKeys=scheduler.getJobKeys(matcher);
			scheduler.deleteJobs(new ArrayList<JobKey>(jobKeys));
			flag=true;
		} catch (SchedulerException e) {
			logger.error("---恢复任务异常---", e);
		}
		return flag;
	}
	
	/**
	 * 修改任务( 先删除后 添加)
	 * @param taskId
	 * @param groupId
	 * @param cron
	 * @param jobDataMap
	 */
	public static boolean modifyJob(Integer taskId,Integer groupId,String cron,String taskName,JobDataMap jobDataMap){
		boolean flag=false;
		try {
			Scheduler scheduler=getScheduler();
			 TriggerKey triggerKey = TriggerKey.triggerKey(String.valueOf("task_"+taskId),"group_"+groupId);    
			 CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey); 
			 if(trigger!=null){ //如果此触发器存在
				 CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cron);         
				// 按新的cronExpression表达式重新构建trigger         
				trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build(); 
				scheduler.rescheduleJob(triggerKey, trigger);
				logger.info("触发器 [ task_"+taskId+"  group_"+groupId+" 已经存在 更新它 ]");
			 }else{
				 	trigger = TriggerBuilder.newTrigger()
			        .withSchedule(CronScheduleBuilder.cronSchedule(cron))
			        .forJob(String.valueOf("task_"+taskId),"group_"+groupId)
			        .withDescription(taskName)
			        .build();
			 }
			 JobKey jobKey= JobKey.jobKey(String.valueOf("task_"+taskId),"group_"+taskId);
			 JobDetail jobDetail=scheduler.getJobDetail(jobKey);
			 if(jobDetail!=null){ //此任务存在删除任务
				 delJob(taskId, groupId);
			 }
			 scheduler.scheduleJob(jobDetail, trigger);
			flag=true;
		} catch (SchedulerException e) {
			logger.error("---修改任务异常---", e);
		}
		return flag;
	}
	
	
	//加载测试的内部类
	private static  class TestScheduler{
		private static  final StdSchedulerFactory sf = new StdSchedulerFactory();
		{
			try {
				Properties props = new Properties();
				props.put("org.quartz.scheduler.instanceName", "testScheduler");
				props.put("org.quartz.threadPool.threadCount", "10");
				sf.initialize(props);
			} catch (SchedulerException e) {
				e.printStackTrace();
			}
		}
		
		public Scheduler getTestScheduler(){
				try {
					Scheduler scheduler = sf.getScheduler();
					return scheduler;
				} catch (SchedulerException e) {
					e.printStackTrace();
				}
				return null;
		}
		
		
		
		/**
		 * 添加用户抓取测试 执行一次
		 * @param jobDetail
		 * @return
		 */
		public  boolean execTestJob(Integer taskId,Integer groupId,String taskName,Map<String, Object> jobMap){
			boolean flag=false;
			try {
				 Scheduler scheduler=this.getTestScheduler();
				 if(scheduler==null){
					 return false;
				 }
				 final JobDataMap dataMap=new JobDataMap();
				 dataMap.putAll(jobMap);
				 JobDetail jobDetail=JobBuilder.newJob()
					        .ofType(CarwlJob.class)
					        .setJobData(dataMap)
					        .withIdentity(String.valueOf("task_test_"+taskId),"group_test_"+groupId)
					        .build();
				 
				 TriggerKey triggerKey = TriggerKey.triggerKey(String.valueOf("task_test_"+taskId),"group_test_"+groupId);    
				 Trigger trigger = scheduler.getTrigger(triggerKey); 
				 if(trigger !=null){
					 trigger.getTriggerBuilder().withIdentity(triggerKey).startNow()
				        .withDescription(taskName)
				        .forJob(jobDetail)
				        .build();
					 scheduler.rescheduleJob(triggerKey, trigger);
				 }else{
					 trigger=TriggerBuilder.newTrigger()
							 	.withIdentity(triggerKey)
							 	.startNow()
						        .withDescription(taskName)
						        .forJob(jobDetail)
						        .build();
				 }
				 JobKey jobKey= JobKey.jobKey(String.valueOf("task_test_"+taskId),"task_test_"+taskId);
				 if(scheduler.getJobDetail(jobKey)!=null){ //如果该任务存在就替换
					 scheduler.addJob(jobDetail, true);
				 }
				 scheduler.scheduleJob(jobDetail, trigger);
				 scheduler.start();
				 flag=true;
			} catch (SchedulerException e) {
				logger.error("---添加任务异常---", e);
			}
			return flag;
		}
		
		
	}
	
	/**
	 * 添加任务
	 * @param jobDetail
	 * @return
	 */
	public static boolean addJob(Integer taskId,Integer groupId,String cron,String taskName,Map<String, Object> jobMap){
		boolean flag=false;
		try {
			Scheduler scheduler=getScheduler();
			 TriggerKey triggerKey = TriggerKey.triggerKey(String.valueOf("task_"+taskId),"group_"+groupId);    
			 CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey); 
			 if(trigger!=null){ //如果此触发器存在
				 CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cron);         
				// 按新的cronExpression表达式重新构建trigger         
				trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build(); 
				scheduler.rescheduleJob(triggerKey, trigger);
				logger.info("触发器 [ task_"+taskId+"  group_"+groupId+" 已经存在 更新它 ]");
			 }else{
				 	trigger = TriggerBuilder.newTrigger().withIdentity(triggerKey)
			        .withSchedule(CronScheduleBuilder.cronSchedule(cron))
			        .forJob(String.valueOf("task_"+taskId),"group_"+groupId)
			        .withDescription(taskName)
			        .build();
			 }
			 final JobDataMap dataMap=new JobDataMap();
			 dataMap.putAll(jobMap);
			 JobDetail jobDetail=JobBuilder.newJob()
				        .ofType(CarwlJob.class)
				        .setJobData(dataMap)
				        .withIdentity(String.valueOf("task_"+taskId),"group_"+groupId)
				        .build();
			 JobKey jobKey= JobKey.jobKey(String.valueOf("task_"+taskId),"group_"+groupId);
			 if(scheduler.getJobDetail(jobKey)!=null){ //如果该任务存在就替换
				 scheduler.addJob(jobDetail, true);
			 }else{
				 scheduler.scheduleJob(jobDetail, trigger);
			 }
			flag=true;
		} catch (SchedulerException e) {
			logger.error("---添加任务异常---", e);
		}
		return flag;
	}
	
	/**
	 * 获取计划中的所有的任务
	 * @return
	 * @throws SchedulerException 
	 */
	public static List<ScheduleJob> getScheduleJobs() throws SchedulerException{
			List<ScheduleJob> scheduleJobs=new ArrayList<ScheduleJob>();
			Scheduler scheduler=getScheduler();
			GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup(); 
			Set<JobKey> jobKeys=scheduler.getJobKeys(matcher);
			for(JobKey jobKey:jobKeys){
				 List<? extends Trigger> triggers=scheduler.getTriggersOfJob(jobKey);
				 for(Trigger trigger:triggers){
					 ScheduleJob scheduleJob=new ScheduleJob();
					 scheduleJob.setCreateDate(trigger.getStartTime());
					 scheduleJob.setDescription(trigger.getDescription());
					 scheduleJob.setJobId(jobKey.getName());
					 scheduleJob.setGroup(jobKey.getGroup());
					 scheduleJob.setUrl(scheduler.getJobDetail(jobKey).getJobDataMap().getString("url"));
					 if(trigger instanceof CronTrigger){
						 CronTrigger cronTrigger=(CronTrigger) trigger;
						 scheduleJob.setCronExpression(cronTrigger.getCronExpression()); //获取表达式
					 }
					 //当前状态
					 TriggerState triggerState=scheduler.getTriggerState(trigger.getKey());
					 scheduleJob.setStatus(triggerState.name());
					 scheduleJobs.add(scheduleJob); 
			}
		}
		return scheduleJobs;
	}
	
	/**
	 * 获取计划中的所有的状态
	 * @return
	 * @throws SchedulerException 
	 */
	public static List<Map<String, Object>> getScheduleJobStatuses() throws SchedulerException{
		Scheduler scheduler=getScheduler();
		List<Map<String, Object>> listStatus=new ArrayList<Map<String, Object>>();
		GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup(); 
		Set<JobKey> jobKeys=scheduler.getJobKeys(matcher);
		for(JobKey jobKey:jobKeys){
			List<? extends Trigger> triggers=scheduler.getTriggersOfJob(jobKey);
			for(Trigger trigger:triggers){
				Map<String, Object> status =new HashMap<String, Object>();
				status.put("id", jobKey.getName());
				status.put("group",jobKey.getGroup());
				TriggerState triggerState=scheduler.getTriggerState(trigger.getKey());
				status.put("status", triggerState.name());
				listStatus.add(status);
			}
		}
		return listStatus;
	}
} 


    (2) 通过RMI实现Quartz远程控制(此方法用的比较少)

    修改quartz.properties 主要属性文件


#==============================================================    
#Configure Main Scheduler Properties    (客户端与服务端)instanceName 必须一致
#==============================================================     
org.quartz.scheduler.instanceName = crawl_scheduler  
org.quartz.scheduler.instanceId = AUTO  

#==============================================================    
#Configure RMI( server )   用于服务端属性
#============================================================== 
#org.quartz.scheduler.rmi.export = true
#org.quartz.scheduler.rmi.createRegistry = true
#org.quartz.scheduler.rmi.registryHost = localhost
#org.quartz.scheduler.rmi.registryPort = 1099
#org.quartz.scheduler.rmi.serverPort = 1100

#==============================================================    
#Configure RMI( client )    客户端调用端属性
#============================================================== 
#org.quartz.scheduler.rmi.proxy = true
#org.quartz.scheduler.rmi.registryHost = localhost
#org.quartz.scheduler.rmi.registryPort = 1099




2. quartz 集群的实现;

    具体的实现参考(https://www.quartz-scheduler.org/generated/2.2.2/html/qtz-all/#page/quartz-scheduler-webhelp%2Fre-cls_cluster_configuration.html%23

    具体的实现很简单,将所有的定时任务都读取一个数据库 quartz 会自动将任务分配(确保一个任务只有一个执行者);

    其实quartz 是通过数据的数据加锁实现 一个任务只有一个执行者,不会出现一个任务多个执行者启动执行的情况;

配置文件一定要有


# 开启集群
org.quartz.jobStore.isClustered = true
#集群的心跳检测
org.quartz.jobStore.clusterCheckinInterval = 20000


3 quartz 一套程序多个实例的实现;

具体参考:http://my.oschina.net/laiweiwei/blog/122280?fromerr=JwLu1rcS

在上面的 SchedulerFactoryManager 中 内部类 TestScheduler 有所实现;
quartz 通过  Scheduler 对象实现管理的;一般此对象为单例的(加载本地quartz.properties 配置文件)实例化对象;
所有可以通过实例化 Scheduler 手动属于属性实现;

{
            try {
                Properties props = new Properties();
                props.put("org.quartz.scheduler.instanceName", "testScheduler");
                props.put("org.quartz.threadPool.threadCount", "10");
                sf.initialize(props);
            } catch (SchedulerException e) {
                e.printStackTrace();
            }
        } 



   

转载于:https://my.oschina.net/haopeng/blog/638563

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值