1. หลักการการใช้งานพื้นฐานของการจัดตารางงานควอตซ์
Quartz เป็นโครงการโอเพนซอร์สในสาขาการจัดตารางงานโดย OpenSymphony ซึ่งขึ้นอยู่กับการใช้งาน Java อย่างสมบูรณ์ ในฐานะที่เป็นกรอบการจัดตารางเวลาโอเพ่นซอร์สที่ยอดเยี่ยมควอตซ์มีคุณสมบัติดังต่อไปนี้:
(1) ฟังก์ชั่นการจัดตารางเวลาที่มีประสิทธิภาพเช่นการสนับสนุนวิธีการกำหนดเวลาที่หลากหลายสามารถตอบสนองความต้องการทั่วไปและความต้องการพิเศษต่างๆ
(2) วิธีแอปพลิเคชันที่ยืดหยุ่นเช่นการสนับสนุนการรวมกันหลายอย่างของงานและการกำหนดเวลาและสนับสนุนวิธีการจัดเก็บข้อมูลหลายวิธีในการจัดตารางข้อมูล
(3) ความสามารถในการกระจายและการจัดกลุ่ม Terracotta ได้ปรับปรุงฟังก์ชั่นดั้งเดิมหลังจากการซื้อกิจการ บทความนี้จะเพิ่มขึ้นในส่วนนี้
1.1 องค์ประกอบหลักควอตซ์
องค์ประกอบหลักของการจัดตารางงานควอตซ์คือ: ตารางเวลากำหนดตารางเวลา, ทริกเกอร์ทริกเกอร์และงานงาน ในกรณีที่ทริกเกอร์และงานเป็นข้อมูลเมตาสำหรับการจัดตารางงานและตัวกำหนดตารางเวลาเป็นคอนโทรลเลอร์ที่ดำเนินการตามกำหนดเวลา
ทริกเกอร์เป็นองค์ประกอบที่ใช้ในการกำหนดเวลาการตั้งเวลานั่นคือตามกฎเวลาที่งานจะถูกดำเนินการ ทริกเกอร์มีสี่ประเภทในควอตซ์: Simpletrigger, Crontirgger, DateIntervaltrigger และ NthincludedDdayTrigger ทริกเกอร์ทั้งสี่เหล่านี้สามารถตอบสนองความต้องการส่วนใหญ่ของแอปพลิเคชันระดับองค์กร
งานใช้เพื่อเป็นตัวแทนของงานที่กำหนด ส่วนใหญ่มีงานสองประเภท: ไร้สัญชาติและรัฐ สำหรับทริกเกอร์เดียวกันงานที่มีสถานะไม่สามารถดำเนินการแบบขนานได้ หลังจากที่งานทริกเกอร์ครั้งสุดท้ายจะถูกดำเนินการสามารถเรียกใช้งานต่อไปได้ โยบมีคุณลักษณะหลักสองประการคือความผันผวนและความทนทานซึ่งความผันผวนหมายถึงงานที่ยังคงอยู่ในการจัดเก็บฐานข้อมูลในขณะที่ความทนทานหมายความว่างานจะถูกเก็บไว้เมื่อไม่มีการเชื่อมโยงทริกเกอร์ ทั้งสองจะคงอยู่หรือเก็บรักษาไว้เมื่อค่าเป็นจริง งานสามารถเชื่อมโยงกับทริกเกอร์หลายตัว แต่ทริกเกอร์สามารถเชื่อมโยงงานเดียวเท่านั้น
Scheduler ถูกสร้างขึ้นโดย Scheduler Factory: DirectSchedulerFactory หรือ StdSchedulerFactory โรงงานที่สองคือ stdschedulerfactory ถูกใช้บ่อยขึ้นเนื่องจาก DirectSchedulerFactory ไม่สะดวกพอที่จะใช้และจำเป็นต้องมีการตั้งค่าการเข้ารหัสด้วยตนเองอย่างละเอียดจำนวนมาก มีสามประเภทหลักของตารางเวลา: Remotembeanscheduler, Remotescheduler และ Stdscheduler
ความสัมพันธ์ระหว่างองค์ประกอบหลักของควอตซ์แสดงในรูปที่ 1.1:
รูปที่ 1.1 แผนภาพความสัมพันธ์องค์ประกอบหลัก
1.2 มุมมองเธรดควอตซ์
ในควอตซ์มีเธรดสองประเภทเธรดตัวกำหนดตารางเวลาและเธรดการดำเนินการงานโดยที่เธรดการดำเนินการงานมักจะใช้พูลเธรดเพื่อรักษากลุ่มของเธรด
รูปที่ 1.2 มุมมองเธรดควอตซ์
มีสองเธรดหลักสำหรับ Scheduler: เธรดที่ดำเนินการกำหนดเวลาปกติและเธรดที่ดำเนินการ MisfiredTrigger การจัดส่งด้ายปกติโพลทริกเกอร์ทั้งหมดที่เก็บไว้ หากมีทริกเกอร์ที่จำเป็นต้องเรียกใช้นั่นคือเวลาของทริกเกอร์ต่อไปจะมาถึงแล้วจะได้รับเธรดที่ไม่ได้ใช้งานจากพูลเธรดการดำเนินการงานเพื่อดำเนินการงานที่เกี่ยวข้องกับทริกเกอร์ เธรด Misfire สแกนทั้งหมดทริกเกอร์เพื่อดูว่ามี misfiredtrigger หรือไม่ ถ้าเป็นเช่นนั้นจะได้รับการจัดการแยกต่างหากตามนโยบาย Misfire (ไฟไหม้ตอนนี้หรือรอไฟต่อไป)
1.3 การจัดเก็บข้อมูลงานควอตซ์
ทริกเกอร์และงานในควอตซ์ต้องเก็บไว้ก่อนที่จะใช้งานได้ มีวิธีการจัดเก็บสองวิธีในควอตซ์: Ramjobstore และ Jobstoresupport ที่ Ramjobstore จัดเก็บทริกเกอร์และงานในหน่วยความจำในขณะที่ JobStoresupport จัดเก็บทริกเกอร์และงานในฐานข้อมูลตาม JDBC Ramjobstore สามารถเข้าถึงได้อย่างรวดเร็ว แต่เนื่องจากข้อมูลทั้งหมดจะหายไปหลังจากระบบหยุดลงจึงต้องใช้ Jobstoresupport ในแอปพลิเคชันคลัสเตอร์
2. หลักการคลัสเตอร์ควอตซ์ 2.1 สถาปัตยกรรมคลัสเตอร์ควอตซ์
แต่ละโหนดในคลัสเตอร์ควอตซ์เป็นแอปพลิเคชันควอตซ์อิสระซึ่งจะจัดการโหนดอื่น ๆ ซึ่งหมายความว่าคุณต้องเริ่มต้นหรือหยุดแต่ละโหนดแยกกัน ในคลัสเตอร์ควอตซ์โหนดควอตซ์อิสระไม่ได้สื่อสารกับโหนดหรือโหนดการจัดการอื่น แต่แทนที่จะรับรู้แอปพลิเคชันควอตซ์อื่นผ่านตารางฐานข้อมูลเดียวกันดังแสดงในรูปที่ 2.1
รูปที่ 2.1 สถาปัตยกรรมคลัสเตอร์ควอตซ์
2.2 ตารางฐานข้อมูลที่เกี่ยวข้องกับคลัสเตอร์ควอตซ์
เนื่องจากคลัสเตอร์ควอตซ์ขึ้นอยู่กับฐานข้อมูลจึงจำเป็นต้องสร้างตารางฐานข้อมูล Quartz ก่อน แพ็คเกจรีลีสควอตซ์ประกอบด้วยสคริปต์ SQL สำหรับแพลตฟอร์มฐานข้อมูลที่รองรับทั้งหมด สคริปต์ SQL เหล่านี้จะถูกเก็บไว้ในไดเรกทอรี <quartz_home>/docs/dbtables Quartz เวอร์ชัน 1.8.4 ที่ใช้ที่นี่มีทั้งหมด 12 ตาราง จำนวนตารางอาจแตกต่างกันในรุ่นที่แตกต่างกัน ฐานข้อมูลคือ MySQL และใช้ tables_mysql.sql เพื่อสร้างตารางฐานข้อมูล ตารางทั้งหมดจะแสดงในรูปที่ 2.2 และการแนะนำสั้น ๆ เกี่ยวกับตารางเหล่านี้แสดงในรูปที่ 2.3
รูปที่ 2.2 ตารางที่สร้างขึ้นในควอตซ์ 1.8.4 ในฐานข้อมูล MySQL
รูปที่ 2.3 ความรู้เบื้องต้นเกี่ยวกับตารางข้อมูลควอตซ์
2.2.1 ตารางสถานะกำหนดตารางเวลา (qrtz_scheduler_state)
คำอธิบาย: ข้อมูลอินสแตนซ์ของโหนดในคลัสเตอร์ควอตซ์อ่านข้อมูลของตารางนี้เป็นประจำเพื่อกำหนดสถานะปัจจุบันของแต่ละอินสแตนซ์ในคลัสเตอร์
instance_name: ชื่อที่กำหนดค่าโดย org.quartz.scheduler.instanceId ในไฟล์การกำหนดค่า หากตั้งค่าเป็นอัตโนมัติควอตซ์จะสร้างชื่อตามชื่อเครื่องทางกายภาพและเวลาปัจจุบัน
last_checkin_time: เวลาเช็คอินล่าสุด
checkin_interval: เวลาเช็คอินเวลา
2.2.2 ตารางทริกเกอร์และงานเชื่อมโยง (qrtz_fired_triggers)
เก็บข้อมูลสถานะที่เกี่ยวข้องกับทริกเกอร์ทริกเกอร์และข้อมูลการดำเนินการของงานที่เกี่ยวข้อง
2.2.3 ตารางข้อมูลทริกเกอร์ (qrtz_triggers)
trigger_name: ชื่อทริกเกอร์ผู้ใช้สามารถปรับแต่งชื่อได้ตามต้องการไม่มีข้อกำหนดบังคับ
trigger_group: ชื่อของกลุ่มทริกเกอร์ซึ่งผู้ใช้สามารถปรับแต่งได้ตามต้องการและไม่มีข้อกำหนดบังคับ
Job_name: คีย์ต่างประเทศของ qrtz_job_details ตาราง job_name
Job_group: qrtz_job_details ตาราง job_group คีย์ต่างประเทศ
trigger_state: สถานะทริกเกอร์ปัจจุบันถูกตั้งค่าเป็นที่ได้มา หากมีการตั้งค่าให้รองานจะไม่ทริกเกอร์
trigger_cron: ประเภททริกเกอร์โดยใช้นิพจน์ cron
2.2.4 ตารางรายละเอียดงาน (qrtz_job_details)
หมายเหตุ: บันทึกรายละเอียดงานตารางจะต้องเริ่มต้นโดยผู้ใช้ตามสถานการณ์จริง
Job_name: ชื่อของงานในคลัสเตอร์ ผู้ใช้สามารถปรับแต่งชื่อได้โดยไม่มีข้อกำหนดบังคับใด ๆ
Job_group: ชื่อของกลุ่มที่งานอยู่ในคลัสเตอร์ซึ่งถูกปรับแต่งโดยผู้ใช้ตามความประสงค์และไม่มีข้อกำหนดที่ถูกบังคับ
JOB_CLASS_NAME: ชื่อแพ็คเกจที่สมบูรณ์ของคลาสการใช้งานงานในคลัสเตอร์ ควอตซ์พบคลาสงานตามเส้นทางนี้ไปยัง ClassPath
IS_DARALE: ไม่ว่าจะคงอยู่ให้ตั้งค่าคุณสมบัตินี้เป็น 1, ควอตซ์จะคงงานไว้ในฐานข้อมูล
Job_data: ฟิลด์หยดที่เก็บวัตถุงานยังคงอยู่
2.2.5 ตารางข้อมูลการอนุญาต (qrtz_locks)
หมายเหตุ: มีการเริ่มต้น DML ที่สอดคล้องกันใน tables_oracle.sql ดังแสดงในรูปที่ 2.4
รูปที่ 2.4 ข้อมูลการเริ่มต้นในตารางข้อมูลการอนุญาตควอตซ์
2.3 กระบวนการสตาร์ทอัพควอตซ์ตัวกำหนดตารางเวลาในคลัสเตอร์
ตัวกำหนดตารางเวลาควอตซ์เองไม่ได้สังเกตว่ามันเป็นคลัสเตอร์และเฉพาะ JDBC Jobstore ที่กำหนดค่าสำหรับกำหนดเวลาเท่านั้นที่จะรู้ เมื่อตัวกำหนดตารางเวลาควอตซ์เริ่มต้นจะเรียกวิธีการกำหนดตารางเวลา () ของ Jobstore ซึ่งบอกกำหนดเวลา Jobstore ว่ามันเริ่มต้นขึ้น เมธอด ScheduLSTARTED () ถูกนำมาใช้ในคลาส JOBSTORESUPPORT คลาส JobStoresUpport กำหนดว่าอินสแตนซ์ของตารางเวลามีส่วนร่วมในคลัสเตอร์ตามการตั้งค่าในไฟล์ Quartz.properties หรือไม่ หากมีการกำหนดค่าคลัสเตอร์อินสแตนซ์ของคลาส ClusterManager ใหม่จะถูกสร้างเริ่มต้นและเริ่มต้น ClusterManager เป็นคลาสอินไลน์ในคลาส JobStoresUpport ที่สืบทอด java.lang.thread มันทำงานเป็นประจำและทำหน้าที่เช็คอินในอินสแตนซ์ของตารางเวลา Scheduler ยังต้องตรวจสอบว่าโหนดคลัสเตอร์อื่น ๆ ล้มเหลวหรือไม่ วงจรการดำเนินการเช็คอินการดำเนินการถูกกำหนดค่าใน Quartz.properties
2.4 การตรวจจับโหนดตัวกำหนดตารางเวลาที่ล้มเหลว
เมื่ออินสแตนซ์ของตารางเวลาดำเนินการเช็คอินจะตรวจสอบว่าอินสแตนซ์ของตารางเวลาอื่น ๆ ยังไม่ได้รับการตรวจสอบในเวลาที่พวกเขาคาดหวังหรือไม่ สิ่งนี้ถูกกำหนดโดยการตรวจสอบว่าค่าของตัวกำหนดตารางเวลาที่บันทึกไว้ในคอลัมน์ Last_Chedk_Time ในตาราง scheduler_state นั้นเร็วกว่า org.quartz.jobstore.clusterCheckInInterval หากไม่มีโหนดอย่างน้อยหนึ่งโหนดในเวลาที่กำหนดไว้ล่วงหน้าแล้วตัวกำหนดตารางเวลาที่ใช้งานจะถือว่าล้มเหลว
2.5 การกู้คืนงานจากกรณีที่ล้มเหลว
เมื่ออินสแตนซ์ของ sheduler ล้มเหลวเมื่อดำเนินงานเป็นไปได้ว่าอินสแตนซ์การทำงานอื่น ๆ จะใช้งานและทำงานอีกครั้ง เพื่อให้บรรลุพฤติกรรมนี้คุณสมบัติการกู้คืนงานที่กำหนดค่าให้กับวัตถุ JobDetail จะต้องตั้งค่าเป็น TRUE (job.setRequestSrecovery (TRUE)) หากคุณสมบัติที่กู้คืนได้ถูกตั้งค่าเป็นเท็จ (ค่าเริ่มต้นเป็นเท็จ) มันจะไม่รันใหม่เมื่อตัวกำหนดตารางเวลาไม่สามารถรันงานได้ มันจะถูกเรียกใช้โดยอินสแตนซ์ตัวกำหนดตารางเวลาอื่นในเวลาทริกเกอร์ถัดไป สามารถตรวจพบอินสแตนซ์ของตารางเวลาได้เร็วแค่ไหนหลังจากความล้มเหลวขึ้นอยู่กับช่วงเวลาการเช็คอินของแต่ละตารางเวลา (เช่น org.quartz.jobstore.clustercheckininterval ที่กล่าวถึงใน 2.3)
3. อินสแตนซ์คลัสเตอร์ควอตซ์ (ควอตซ์+สปริง)
3.1 ฤดูใบไม้ผลิเข้ากันไม่ได้กับปัญหาควอตซ์
ฤดูใบไม้ผลิไม่รองรับควอตซ์อีกต่อไปตั้งแต่ 2.0.2 โดยเฉพาะเมื่อ Quartz+Spring Instantiates งานของ Quartz ลงในฐานข้อมูลจะเกิดข้อผิดพลาดแบบอนุกรมที่เกิดขึ้นได้:
<bean id = "jobtask"> <property name = "targetObject"> <ref bean = "quartzjob"/> </property> <property name = "TargetMethod"> <danue> ดำเนินการ </alue> </porement> </ebean>
วิธีการใช้วิธีการในคลาส MethodInvokingJobDetailFactoryBean ไม่รองรับการทำให้เป็นอนุกรมดังนั้นมันจะทำให้เกิดข้อผิดพลาดเมื่อทำให้งานของควอตซ์อยู่ในฐานข้อมูล
ก่อนอื่นให้แก้ปัญหาของ MethodInvokingJobDetailFactoryBean โดยไม่ต้องแก้ไขซอร์สโค้ดสปริงคุณสามารถหลีกเลี่ยงการใช้คลาสนี้และโทรหา JobDetail โดยตรง อย่างไรก็ตามการใช้งาน JobDetail คุณต้องใช้ตรรกะของ mothodinvoking ด้วยตัวเอง คุณสามารถใช้คุณสมบัติ JobClass และ JobDataasmap ของ JobDetail เพื่อปรับแต่งโรงงาน (ผู้จัดการ) เพื่อให้บรรลุวัตถุประสงค์เดียวกัน ตัวอย่างเช่นในตัวอย่างนี้ MyDetailquartzjobbean ใหม่ถูกสร้างขึ้นเพื่อใช้งานฟังก์ชั่นนี้
3.2 ไฟล์ myDetailquartzjobbean.java
แพ็คเกจ org.lxh.mvc.jobbean; นำเข้า java.lang.reflect.method นำเข้า org.apache.commons.logging.log; นำเข้า org.apache.commons.logging.logfactory; นำเข้า org.quartz org.springframework.context.applicationContext; นำเข้า org.springframework.scheduling.quartz.quartzjobbean; คลาสสาธารณะ mydetailquartzjobbean ขยาย Quartzjobbean สตริงส่วนตัว TargetObject; สตริงส่วนตัว targetMethod; Private ApplicationContext CTX; Void Protected ExecuteInternal (jobExecutionContext Context) พ่น jobExecutionException {ลอง {logger.info ("ดำเนินการ [" + targetObject + "] ในครั้งเดียว >>>>>>"); Object oargetObject = ctx.getBean (targetObject); วิธี m = null; ลอง {m = oargetObject.getClass (). getMethod (targetMethod, คลาสใหม่ [] {}); M.Invoke (OargetObject, ใหม่วัตถุ [] {}); } catch (SecurityException e) {logger.error (e); } catch (nosuchmethodexception e) {logger.error (e); }} catch (exception e) {โยน jobExecutionException ใหม่ (e); }} โมฆะสาธารณะ setApplicationContext (ApplicationContext ApplicationContext) {this.ctx = ApplicationContext; } โมฆะสาธารณะ SettArgetObject (สตริง targetObject) {this.targetObject = targetObject; } โมฆะสาธารณะ SetTargetMethod (String TargetMethod) {this.targetMethod = TargetMethod; -3.3 คลาสการใช้งานจริง
ในคลาสทดสอบฟังก์ชั่นของการพิมพ์เวลาปัจจุบันของระบบถูกนำไปใช้อย่างง่าย ๆ
แพ็คเกจ org.lxh.mvc.job; นำเข้า java.io.serializable; นำเข้า java.util.date; นำเข้า org.apache.commons.logging.log; นำเข้า org.apache.Commons.logging.logfactory; การทดสอบระดับสาธารณะ ส่วนตัวคงที่สุดท้าย Long SerialVersionUid = -2073310586499744415L; โมฆะสาธารณะดำเนินการ () {วันที่ = วันที่ใหม่ (); System.out.println (date.tolocalestring ()); -3.4 กำหนดค่าไฟล์ quartz.xml
<bean id = "test" scope = "prototype"> </epean> <bean id = "testjobtask"> <property name = "JobClass"> <value> org.lxh.mvc.jobbean.mydetailquartzjobbean </ค่า> key = "targetMethod" value = "EXECUTE"/> </map> </คุณสมบัติ> </ebean> <bean name = "TestTrigger"> <property name = "JobDetail" ref = "testJobTask"/> <property name = "cronexpression" value = "0/1 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /> </ebean> <bean id = "quartzscheduler"> <property name = "configlocation" value = "classpath: quartz.properties"/> <property name = "ทริกเกอร์"> <list> <ref bean = "testtrigger"/>
3.5 ทดสอบ
รหัสและการกำหนดค่าของ Servera และ ServerB นั้นเหมือนกันทุกประการ เริ่มต้นเซิร์ฟเวอร์ก่อนจากนั้นเริ่ม ServerB หลังจากปิดเซิร์ฟเวอร์ ServerB จะตรวจสอบการปิดและรับช่วงงานที่ดำเนินการบนเซิร์ฟเวอร์และดำเนินการต่อ
4. อินสแตนซ์คลัสเตอร์ควอตซ์ (ควอตซ์เดี่ยว)
แม้ว่าเราได้ใช้การกำหนดค่าคลัสเตอร์ของสปริง+ควอตซ์ แต่ก็ยังไม่แนะนำให้ใช้วิธีนี้เนื่องจากปัญหาความเข้ากันได้ระหว่างฤดูใบไม้ผลิและควอตซ์ ในส่วนนี้เราใช้คลัสเตอร์ที่กำหนดค่าแยกต่างหากด้วยควอตซ์ซึ่งง่ายและเสถียรเมื่อเทียบกับสปริง+ควอตซ์
4.1 โครงสร้างวิศวกรรม
เราใช้ควอตซ์เพียงอย่างเดียวเพื่อใช้ฟังก์ชั่นคลัสเตอร์โครงสร้างรหัสและแพ็คเกจ JAR ของบุคคลที่สามที่ต้องการดังแสดงในรูปที่ 3.1 ในหมู่พวกเขาเวอร์ชัน MySQL: 5.1.52 และรุ่นไดรเวอร์ MySQL: mysql-connector-java-5.1.5-bin.jar (สำหรับ 5.1.52 แนะนำให้ใช้ไดรเวอร์รุ่นนี้เนื่องจากมีข้อบกพร่องในควอตซ์
รูปที่ 4.1 โครงสร้างวิศวกรรมคลัสเตอร์ควอตซ์และแพ็คเกจขวดที่สามของบุคคลที่สามที่ต้องการ
ในหมู่พวกเขา Quartz.properties เป็นไฟล์การกำหนดค่าควอตซ์และวางไว้ในไดเรกทอรี SRC หากไม่มีไฟล์ดังกล่าว Quartz จะโหลดไฟล์ Quartz.properties โดยอัตโนมัติในแพ็คเกจ JAR SimpleCoveryJob.Java และ SimpleReCoveryStatefulJob.java เป็นสองงาน ClusterExample.java เขียนข้อมูลการตั้งเวลากลไกการเรียกใช้และฟังก์ชั่นหลักการทดสอบที่สอดคล้องกัน
4.2 การกำหนดค่าไฟล์ quartz.properties
ชื่อไฟล์เริ่มต้น quartz.properties ใช้เพื่อเปิดใช้งานคุณสมบัติคลัสเตอร์โดยการตั้งค่า "org.quartz.jobstore.isclustered" คุณสมบัติเป็น "true" แต่ละอินสแตนซ์ในคลัสเตอร์จะต้องมี "ID อินสแตนซ์อินสแตนซ์" ที่ไม่ซ้ำกัน ("org.quartz.scheduler.instanceId" คุณสมบัติ) แต่ควรมี "ชื่ออินสแตนซ์ตัวกำหนดตารางเวลาเดียวกัน" ("org.quartz.scheduler.instancename") ซึ่งหมายความว่าแต่ละอินสแตนซ์ ยกเว้นข้อยกเว้นต่อไปนี้เนื้อหาของไฟล์กำหนดค่าจะต้องเหมือนกัน:
. ขนาดสระว่ายน้ำ
ข. แตกต่างกัน "org.quartz.scheduler.instanceId" ค่าแอตทริบิวต์ (เพียงตั้งค่าเป็น "auto")
- - - - - - - - auto#================================================================================================================================= - org.quartz.jobstore.impl.jdbcjobstore.jobstoretxorg.quartz.jobstore.driverdelegateclass = org.quartz.impl.jdbcjobstore.stdjdbcdelegateorg.quartz.jobstore qrtz_org.quartz.jobstore.isclustered = trueorg.quartz.jobstore.clustercheckininterval = 10,000 org.quartz.jobstore.datasource = myds - - - - #====================================================================================== com.mysql.jdbc.driverg.quartz.datasource.myds.url = jdbc: mysql: //192.168.31.18: 3306/ทดสอบ? useunicode = true & areamentencoding = utf-8org.quartz.datasource rootorg.quartz.datasource.myds.password = 123456org.quartz.datasource.myds.maxconnections = 30#================================================================================= - - - - - - - org.quartz.simpl.simplethreathreadpoolorg.quartz.threadpool.threadcount = 5org.quartz.threadpool.threadpriority = 5org.quartz.threadpool.threadsinteritcontextclasslassloaderofinitializingthread
4.3 ไฟล์ ClusterExample.java
แพ็คเกจคลัสเตอร์; นำเข้า java.util.date; นำเข้า org.quartz.jobdetail; นำเข้า org.quartz.scheduler; นำเข้า org.quartz.schedulerfactory นำเข้า org.quartz.simpletrigger; โยนข้อยกเว้น {system.out.println ("**** ลบงาน/ทริกเกอร์ที่มีอยู่ *****"); // unschedule jobs string [] กลุ่ม = inscheduler.gettriggergroupnames (); สำหรับ (int i = 0; i <groups.length; i ++) {string [] names = inscheduler.getTriggerNames (กลุ่ม [i]); สำหรับ (int j = 0; j <names.length; j ++) {inscheduler.unschedulejob (ชื่อ [j], กลุ่ม [i]); }} // ลบกลุ่มงาน = inscheduler.getJobGroupNames (); สำหรับ (int i = 0; i <groups.length; i ++) {string [] names = inscheduler.getJobnames (กลุ่ม [i]); สำหรับ (int j = 0; j <names.length; j ++) {inscheduler.deletejob (ชื่อ [j], กลุ่ม [i]); }}} การเรียกใช้โมฆะสาธารณะ (บูลีน Selecrearjobs, บูลีน inschedulejobs) โยนข้อยกเว้น {// ก่อนอื่นเราต้องได้รับการอ้างอิงไปยัง scheduler schedulerfactory sf = ใหม่ stdschedulerfactory (); scheduler schede = sf.getscheduler (); if (sulearjobs) {cleanup (schede); } system.out.println ("-------------------------------"); if (inschedulejobs) { System.out.println ("-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- execute งานนี้อีกครั้งหากกำลังดำเนินการเมื่อ // ตัวกำหนดเวลาลงไป ... job.setRequestSrecovery (จริง); ที่: " + trigger.getNextFireTime () +" และทำซ้ำ: " + trigger.getRepeatCount () +" ครั้งทุกครั้ง " + trigger.getRepeatInterval () / 1000 +" วินาที "); scheduLjob (Job, trigger); count ++; กำหนดเวลาอีกครั้งเพื่อดำเนินการงานนี้หากกำลังดำเนินการเมื่อ // ตัวกำหนดเวลาลง ... job.setRequestSrecovery (เท็จ); ที่: " + trigger.getNextFireTime () +" และทำซ้ำ: " + trigger.getRepeatCount () +" ครั้งทุกครั้ง " + trigger.getRepeatInterval () / 1000 +" วินาที "); System.out.println ("------------------------------------"); System.out.println ("---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 1000L); System.out.println ("-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - args.length; -4.4 SimpleerecoveryJob.java
แพ็คเกจคลัสเตอร์; นำเข้า java.io.serializable; นำเข้า java.util.date; นำเข้า org.apache.commons.logging.log; นำเข้า org.apache.commons.logging.logfactory; นำเข้า org.quartz.job; ที่คุณต้องการดำเนินการซ้ำ ๆ เขียนรหัสที่เกี่ยวข้องในวิธีการดำเนินการหลักฐานคือ: ใช้งานอินเตอร์เฟสงาน // สำหรับเมื่อคลาส SimpleJob ถูกสร้างอินสแตนซ์และเมื่อมีการเรียกวิธีการดำเนินการเราไม่จำเป็นต้องให้ความสนใจกับมัน Public SimplerecoveryJob () {} โมฆะสาธารณะดำเนินการ (jobExecutionContext บริบท) พ่น jobExecutionException {// งานนี้เพียงแค่พิมพ์ชื่องานและเวลาที่งานกำลังเรียกใช้สตริง jobName = context.getJobDetail () getFullName (); System.out.println ("Job 1111111111111111 SimplerecoveryJob พูดว่า:" + JobName + "การดำเนินการที่" + วันที่ใหม่ ()); -4.5 ผลการดำเนินงาน
การกำหนดค่าและรหัสในเซิร์ฟเวอร์ A และเซิร์ฟเวอร์ B เหมือนกันทุกประการ วิธีการรัน: เรียกใช้ ClusterExample.java บนโฮสต์ใด ๆ เพิ่มงานลงในตารางและสังเกตผลลัพธ์การรัน:
เรียกใช้เซิร์ฟเวอร์ผลลัพธ์จะแสดงในรูปที่ 4.2
รูปที่ 4.2 ผลการดำเนินการเซิร์ฟเวอร์ 1
หลังจากเปิดใช้งาน ServerB เอาต์พุตของ Servera และ ServerB จะแสดงในรูปที่ 4.3 และ 4.4
รูปที่ 4.3 Servera Running ผลลัพธ์ 2
รูปที่ 4.4 ผลการดำเนินการ ServerB 1
จะเห็นได้จากรูปที่ 4.3 และ 4.4 ที่เปิดใช้งาน ServerB ระบบจะตระหนักถึงความรับผิดชอบต่อยอดคงเหลือโดยอัตโนมัติและ ServerB จะใช้งาน Job1 โดยอัตโนมัติ หลังจากปิดเซิร์ฟเวอร์แล้วผลลัพธ์การรันของ ServerB จะแสดงในรูปที่ 4.5
รูปที่ 4.5 ผลการดำเนินการ ServerB 2
ดังที่เห็นได้จากรูปที่ 4.5 ServerB สามารถตรวจพบว่าเซิร์ฟเวอร์หายไปรับช่วงงาน Job2 และสูญเสียเซิร์ฟเวอร์ไปยัง Job2 ที่ต้องดำเนินการในช่วงเวลายกเว้นนี้
5. สิ่งที่ควรทราบ
5.1 ปัญหาการซิงโครไนซ์เวลา
ควอตซ์ไม่สนใจว่าคุณจะเรียกใช้โหนดบนเครื่องเดียวกันหรืออื่น ๆ เมื่อวางคลัสเตอร์บนเครื่องที่แตกต่างกันมันจะเรียกว่าคลัสเตอร์แนวนอน เมื่อโหนดทำงานบนเครื่องเดียวกันมันจะเรียกว่าคลัสเตอร์แนวตั้ง สำหรับกลุ่มแนวตั้งมีปัญหาของความล้มเหลวจุดเดียว สิ่งนี้ไม่สามารถยอมรับได้สำหรับแอปพลิเคชันที่มีความพร้อมใช้งานสูงเนื่องจากเมื่อเครื่องขัดข้องโหนดทั้งหมดจะถูกยกเลิก สำหรับกลุ่มแนวนอนมีปัญหาในการซิงโครไนซ์เวลา
โหนดใช้การประทับเวลาเพื่อแจ้งอินสแตนซ์อื่น ๆ ของเวลาเช็คอินล่าสุดของตัวเอง หากนาฬิกาของโหนดถูกตั้งค่าเป็นเวลาในอนาคตตัวกำหนดตารางเวลาจะไม่ทราบว่าโหนดได้ลดลงอีกต่อไป ในทางกลับกันหากนาฬิกาของโหนดถูกตั้งค่าเป็นเวลาที่ผ่านมาบางทีโหนดอื่น ๆ จะเป็นตัวกำหนดว่าโหนดได้หลุดออกมาและพยายามที่จะรับงานและรันใหม่ วิธีที่ง่ายที่สุดในการซิงโครไนซ์นาฬิกาคอมพิวเตอร์คือการใช้เซิร์ฟเวอร์เวลาอินเทอร์เน็ต
5.2 ปัญหาของโหนดที่แข่งขันกันเพื่องาน
เนื่องจากควอตซ์ใช้อัลกอริทึมการปรับสมดุลการโหลดแบบสุ่มงานจึงถูกดำเนินการโดยอินสแตนซ์ที่แตกต่างกันในแบบสุ่ม เว็บไซต์ทางการของ Quartz กล่าวว่าในปัจจุบันไม่มีวิธีการกำหนด (PIN) งานให้กับโหนดเฉพาะในคลัสเตอร์
5.3 ปัญหาเพื่อรับรายการงานจากคลัสเตอร์
ขณะนี้หากคุณไม่ได้ป้อนการสืบค้นฐานข้อมูลโดยตรงไม่มีวิธีง่ายๆในการรับรายการงานที่ดำเนินการทั้งหมดในคลัสเตอร์ การขออินสแตนซ์ของตารางเวลาจะได้รับรายการงานที่ทำงานบนอินสแตนซ์นั้นเท่านั้น เว็บไซต์อย่างเป็นทางการของ Quartz แนะนำให้คุณได้รับข้อมูลงานทั้งหมดจากตารางที่เกี่ยวข้องโดยการเขียนรหัส JDBC บางส่วนเพื่อเข้าถึงฐานข้อมูล
สรุป
ข้างต้นเป็นเนื้อหาทั้งหมดของบทความนี้ ฉันหวังว่าเนื้อหาของบทความนี้จะมีค่าอ้างอิงบางอย่างสำหรับการศึกษาหรือที่ทำงานของทุกคน หากคุณมีคำถามใด ๆ คุณสามารถฝากข้อความไว้เพื่อสื่อสาร ขอบคุณสำหรับการสนับสนุน Wulin.com