公司在使用Spring Cloud微服务架构,同时都使用Quartz任务框架进行任务调度,具体的结构如下所示:
配置具体见我的另一博文 http://blog.csdn.net/u011687186/article/details/72461102
但是存在这样一个问题,各个服务互相不相关,假如一个发起Job任务的服务挂掉以后,在到达执行任务的时间时,其它服务会执行这个任务,由于其它服务中没有这个Job类,就会报错,并且把这个job的状态变为ERROR,这样可不行。
后来我的解决思路是,把任务单独起一个JOB服务器出来,其它的服务需要执行任务的时候,向这个JOB服务器发送。
但是这样又有一个问题,就是当在任务服务器将要执行任务的时候,需要完成任务的类在其它的服务器上,这个这么办,后来我想到了SpringCloud Ribbon,我把服务暴露了,在保存job的时候,把相应的(服务器1)的地址也保存上,然后在执行类的时候向(服务器1)使用Ribbon就行通信调用,
/**
* Created by mengxiangrui on 2017/6/15.
*/
public class QuartzJob implements Job {
@Resource
private RestTemplate restTemplate;
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
//获取JobDataMap
JobDataMap dataMap = jobExecutionContext.getJobDetail().
getJobDataMap();
String url = (String) dataMap.get(QuartzComn.url);
JSONObject jsonObject = new JSONObject();
for (Map.Entry<String,Object> entry : dataMap.entrySet()) {
if(!QuartzComn.url.equals(entry.getKey())){
jsonObject.put(entry.getKey(),entry.getValue());
}
}
restTemplate.getForEntity(url,Boolean.class,jsonObject);
}
}
但是这样做,把所有的任务都放在了一台服务器上压力比较大,并且各个服务间耦合度较大,偏离的服务化的思想,还是想用原方法配置的方式解决,后来经过研究发现Quartz可以区分使用设置 SchedulerFactoryBean的名称,
我们把每个服务的SchedulerFactoryBean按照服务名称命名,就解决了服务宕机任务报错问题。
SchedulerFactoryBean factory = new SchedulerFactoryBean();
factory.setSchedulerName(NoticeConstant.quartzScheduleName);
// this allows to update triggers in DB when updating settings in config file:
factory.setOverwriteExistingJobs(true);
factory.setJobFactory(jobFactory);
factory.setDataSource(dataSource);
factory.setQuartzProperties(quartzProperties());
return factory;
设置SchedulerFactoryBean的作用。
SCHED_NAME VARCHAR(120) NOT NULL COMMENT 'Scheduler名称,同一集群下的Scheduler实例名称相同,Instance_Id不同'