公司在使用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不同'