สิ่งที่ฉันสงสัยว่าปัญหาคือ setOverwriteExistingJobs ของ SchedulerFactoryBean ไม่ได้ให้การป้องกันที่เพียงพอ
โหนดหนึ่งจะเริ่มต้นตัวกำหนดตารางเวลา และจะตัดสินใจแทนที่ทริกเกอร์ (เบรกพอยต์ org.quartz.impl.jdbcjobstore.SimpleTriggerPersistenceDelegate#deleteExtenstedTriggerProperties )
หลังจากที่ดำเนินการตามวิธีนี้แล้ว ทริกเกอร์จะไม่อยู่ในฐานข้อมูลอีกต่อไป ดังนั้นเมื่อโหนดอื่นในคลัสเตอร์จะพยายามอ่าน (org.quartz.impl.jdbcjobstore.JobStoreSupport#retrieveTrigger) ทริกเกอร์จะล้มเหลวโดยมีข้อยกเว้นด้านล่าง . เนื่องจากข้อยกเว้นนี้ แอปพลิเคชันทั้งหมดจะล้มเหลวในการเริ่มต้น (ไม่ใช่แค่ตัวกำหนดเวลา)
เกิดจาก: org.quartz.JobPersistenceException: ไม่สามารถดึงทริกเกอร์: ไม่พบบันทึกสำหรับการเลือกทริกเกอร์ด้วยคีย์:
สามารถดูบันทึกได้ที่ https://github.com/apixandru/case-study/tree/master/spring-boot-quartz/logs (สามารถพบข้อยกเว้นบนโหนด Server-1 หลังจากรีสตาร์ทครั้งที่ 4)
สำหรับโครงการทั้งหมดที่แสดงให้เห็นถึงปัญหานี้ ให้ไปที่ https://github.com/apixandru/case-study/tree/master/spring-boot-quartz
วิธีที่เรากำหนดค่าตัวกำหนดตารางเวลาอยู่ที่นี่
@Bean
JobDetailFactoryBean jobFactoryBean() {
JobDetailFactoryBean bean = new JobDetailFactoryBean();
bean.setDurability(true);
bean.setName("Sampler");
bean.setJobClass(SampleJob.class);
return bean;
}
@Bean
SimpleTriggerFactoryBean triggerFactoryBean(JobDetailFactoryBean jobFactoryBean) {
SimpleTriggerFactoryBean bean = new SimpleTriggerFactoryBean();
bean.setName("Sampler Trigger");
bean.setRepeatInterval(20_000);
bean.setJobDetail(jobFactoryBean.getObject());
return bean;
}
@Bean
SchedulerFactoryBean schedulerFactoryBean(SimpleTriggerFactoryBean triggerFactoryBean, DataSource dataSource, Dependency dependency) {
Properties props = new Properties();
props.put("org.quartz.scheduler.instanceId", "AUTO");
props.put("org.quartz.jobStore.isClustered", "true");
SchedulerFactoryBean bean = new SchedulerFactoryBean();
bean.setTriggers(triggerFactoryBean.getObject());
bean.setSchedulerName("Demo Scheduler");
bean.setSchedulerContextAsMap(Collections.singletonMap("dependency", dependency));
bean.setOverwriteExistingJobs(true);
bean.setDataSource(dataSource);
bean.setQuartzProperties(props);
return bean;
}
สิ่งนี้เกิดขึ้นบ่อยครั้งบนเซิร์ฟเวอร์งานของเรา แต่การเข้าถึงภายในเครื่องนั้นยากกว่ามาก (อาจเป็นเพราะเซิร์ฟเวอร์จริงนั้นทุ่มเทและมีพลังมากกว่าเครื่องในพื้นที่ของฉันมาก?)
หากต้องการรับจุดบกพร่องบนเครื่องใดๆ ให้เริ่มเซิร์ฟเวอร์หนึ่งเครื่องในโหมดแก้ไขจุดบกพร่องและวางเบรกพอยต์บน SimpleTriggerPersistenceDelegate.deleteExtensedTriggerProperties และหลังจากดำเนินการแล้ว ให้เริ่มเซิร์ฟเวอร์ตัวที่สอง แล้วคุณจะได้รับข้อยกเว้นนี้
อย่างไรก็ตาม ฉันจัดการเพื่อรับข้อผิดพลาดนี้ภายในเครื่องเช่นกันหลังจากปรับใช้ใหม่กับเซิร์ฟเวอร์เว็บลอจิกคลัสเตอร์ในเครื่องของฉันประมาณ 40 ครั้ง