Kata pengantar
Untuk memastikan ketersediaan tinggi dan konkurensi aplikasi yang tinggi, banyak node umumnya digunakan; Untuk tugas waktu, jika setiap node melakukan tugas waktu sendiri, ia mengkonsumsi sumber daya sistem di satu sisi.
Di sisi lain, beberapa tugas dieksekusi beberapa kali, yang dapat menyebabkan masalah logika aplikasi, sehingga sistem penjadwalan terdistribusi diperlukan untuk mengoordinasikan setiap node untuk melakukan tugas waktu.
Spring mengintegrasikan kuarsa
Kuarsa adalah sistem penjadwalan tugas yang matang. Musim semi kompatibel dengan kuarsa untuk pengembangan yang mudah. Mari kita lihat bagaimana mengintegrasikannya:
1. File ketergantungan Maven
<dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>4.3.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>4.3.5.RELEASE</version> </Dependency> <dependency> <GroupId> org.springframework </groupId> <ArTifactId> spring-tx </t Artifactid> <version> 4.3.5.release </version> </dependency> <truppingD> </org.springframework </groupid> <Artifactid> <TROP-JDBC </version. <dependency> <GroupId> org.quartz-Scheduler </groupId> <ArTifactId> quartz </arttifactid> <version> 2.2.3 </version> </dependency> <dependency> <groupid> MySQL </groupid> <ArtifactId> MySQL-Connector-java </Articid> <ArTifacTID> MYSQL-Connector-Connector-java </ArticiCID> <ArtifactD> MYSQL-Connector-Connector-Java </Articl </dependensi>
Yang utama adalah perpustakaan terkait musim semi, perpustakaan kuarsa dan perpustakaan driver MySQL. Catatan: Penjadwalan terdistribusi memerlukan penggunaan basis data, dan MySQL dipilih di sini;
2. Konfigurasikan pekerjaan
Ada dua cara untuk mengonfigurasi pekerjaan, yaitu: MethodInvokingJoBdetailFactoryBean dan JobDetailFactoryBean
2.1methodinvokingjoBdetailFactoryBean
Ketika Anda ingin memanggil metode kacang tertentu, konfigurasi spesifik adalah sebagai berikut:
<bean id = "firstTask"> <name properti = "targetObject" ref = "firstservice" /> <name properti = "targetMethod" value = "service" /> </eal>
2.2JOBDetailFactoryBean
Metode ini lebih fleksibel dan dapat mengatur parameter yang lewat, sebagai berikut:
<bean id="firstTask"> <property name="jobClass" value="zh.maven.SQuartz.task.FirstTask" /> <property name="jobDataMap"> <map> <entry key="firstService" value-ref="firstService" /> </map> </property></bean>
Kelas tugas yang ditentukan oleh JobClass mewarisi kuarzjobbean dan mengimplementasikan metode eksekusionternal; JobDatamap digunakan untuk meneruskan data ke pekerjaan itu
3. Konfigurasikan pemicu yang digunakan untuk penjadwalan
Dua jenis pemicu juga disediakan: SimpleTriggerFactoryBean dan CrontriggerFactoryBean
Fokus pada CrontriggerFactoryBean, tipe ini lebih fleksibel, sebagai berikut:
<bean id = "firstcrontrigger"> <name properti = "jobdetail" ref = "firstTask" /> <name properti = "cronexpression" value = "0/5 * *? * *" /> < /bean>
JobDetail menentukan pekerjaan yang dikonfigurasi pada langkah 2, dan cronexpression dikonfigurasi untuk menjalankan pekerjaan setiap 5 detik;
4. Mengkonfigurasi penjadwalan dari penjadwal kuarsa
Ada juga dua metode: memori ramjobstore dan metode database
4.1 Memori Ramjobstore
Informasi terkait pekerjaan disimpan dalam memori, dan setiap node menyimpannya sendiri, saling mengisolasi, dan dikonfigurasi sebagai berikut:
<ean> <name properti = "triggers"> <cist> <ref bean = "firstcrontrigger"/> </list> </propert> </bean>
4.2 Metode Basis Data
Informasi yang relevan dari pekerjaan disimpan dalam database. Semua node berbagi database. Setiap node berkomunikasi melalui database untuk memastikan bahwa suatu pekerjaan hanya akan dieksekusi pada satu node secara bersamaan.
Jika sebuah node gagal, pekerjaan akan ditugaskan ke node lain untuk dieksekusi. Konfigurasi spesifiknya adalah sebagai berikut:
<bean id = "DataSource" Destroy-Method = "Tutup"> <nama properti = "driverclass" value = "com.mysql.jdbc.driver" /> <name properti = "jdbcurl" nilai = "jdbc = mysql: // localhost: 330 /quartz" nilai "" "" "" "" "" "" "" "" "name" name = "" name = "" name = "" name "" name = "" name = "" name = "" name = "" name = "" "" </bean> <bean> <name properti = "DataSource" ref = "DataSource"/> <name properti = "configLocation" value = "classpath: quartz.properties"/> <name properti = "triggers"> <list> <ref bean = "firstcrontrigger"/</list> </property> </bean> bean = "firstcrontrigger"/</list> </property> </propert
DataSource digunakan untuk mengonfigurasi sumber data dan informasi terkait tabel data. Anda dapat mengunduh paket GZ dari situs web resmi. File SQL berada di bawah jalur: Docs/DBTables, yang menyediakan file SQL untuk database utama;
File kuarsa.properties yang dikonfigurasi dalam configLocation ada di paket org.quartz dari quartz.jar, yang menyediakan beberapa data default, seperti org.quartz.jobstore.class
org.quartz.jobstore.class: org.quartz.simpl.ramjobstore
Di sini Anda perlu menyalin kuarsa.properties dan membuat beberapa modifikasi. Modifikasi spesifik adalah sebagai berikut:
org.quartz.scheduler.instanceID: autoorg.quartz.jobstore.class: org.quartz.impl.jdbcjobstore.jobstoretxorg.quartz.jobstore.isclustered: trueorg.quartz.jobstore.clusterchinchinnecher.isclustered: trueorg.quartz.jobstore.clusterchinchinor
5. Kategori Terkait
kelas publik FirstTask memperluas kuarsajobbean {private firstservice firstservice; @Override Protected Void ExecuteInternal (Konteks JobExecutionContext) melempar JobExecutionException {firstService.Service (); } public void setFirstService (FirstService FirstService) {this.firstservice = firstService; }}FirstTask mewarisi kuarzjobbean, mengimplementasikan metode eksekusionternal, dan panggilan FirstService
kelas publik FirstService mengimplementasikan serializable {private static final long serialversionuid = 1l; public void service () {System.out.println (new SimpleDateFormat ("yyymmdd hh: mm: ss"). format (new date ()) + "--- mulai firstservice"); coba {thread.sleep (2000); } catch (InterruptedException e) {E.PrintStackTrace (); } System.out.println (new SimpleDateFormat ("yyymmdd hh: mm: ss"). Format (new date ()) + "--- end firstservice"); }}Layanan pertama perlu menyediakan antarmuka serialisasi karena perlu disimpan dalam database;
aplikasi kelas publik {public static void main (string [] args) {AbstractApplicationContext context = new ClassPathXMLapPlicationContext ("quartz.xml"); }}Kelas utama digunakan untuk memuat file konfigurasi kuarsa;
Uji penjadwalan terdistribusi
1. Mulai aplikasi dua kali pada saat yang sama dan amati log:
20180405 14:48:10 --- Mulai FirstService
20180405 14:48:12 ---- Akhir Layanan Pertama
20180405 14:48:15 --- Mulai layanan pertama
20180405 14:48:17 ---- Akhir Layanan Pertama
Di antara mereka, A1 memiliki output log, tetapi A2 tidak; Ketika A1 dihentikan, A2 memiliki output log;
2. Tambahkan pekerjaan baru dan buat pekerjaan baru: masing -masing SecondTask dan SecondService. Tambahkan file konfigurasi yang relevan secara bersamaan. Mulai aplikasi dua kali dan amati log:
Log A1 adalah sebagai berikut:
20180405 15:03:15 --- Mulai FirstService
20180405 15:03:15 --- Mulai layanan kedua
20180405 15:03:17 ---- Akhir Layanan Pertama
20180405 15:03:17 --- End SecondService
20180405 15:03:20 --- Mulai FirstService
20180405 15:03:22 ---- Akhir Layanan Pertama
20180405 15:03:25 --- Mulai FirstService
20180405 15:03:27 ---- Akhir Layanan Pertama
Log A2 adalah sebagai berikut:
20180405 15:03:20 --- Mulai layanan kedua
20180405 15:03:22 --- Akhir SecondService
20180405 15:03:25 --- Mulai layanan kedua
20180405 15:03:27 --- Akhir SecondService
Dapat ditemukan bahwa baik A1 dan A2 memiliki tugas eksekusi, tetapi tugas yang sama hanya akan dieksekusi pada satu node pada saat yang sama, dan dimungkinkan untuk ditugaskan ke node lain setelah eksekusi selesai;
3. Jika waktu interval kurang dari waktu eksekusi tugas, misalnya, di sini diubah menjadi tidur (6000)
Log A1 adalah sebagai berikut:
20180405 15:14:40 --- Mulai Layanan Pertama
20180405 15:14:45 --- Mulai layanan pertama
20180405 15:14:46 ---- Akhir Layanan Pertama
20180405 15:14:50 --- Mulai FirstService
20180405 15:14:50 --- Mulai layanan kedua
20180405 15:14:51 --- Akhiri Layanan Pertama
Log A2 adalah sebagai berikut:
20180405 15:14:40 --- Mulai layanan kedua
20180405 15:14:45 --- Mulai layanan kedua
20180405 15:14:46 --- Akhir SecondService
20180405 15:14:51 --- Akhir SecondService
Intervalnya adalah 5 detik, sedangkan eksekusi tugas memakan waktu 6 detik. Mengamati log, Anda dapat menemukan bahwa tugas belum berakhir dan tugas baru telah dimulai. Situasi ini dapat menyebabkan masalah logis dalam aplikasi, yang sebenarnya merupakan pertanyaan apakah tugas tersebut dapat mendukung serial;
4. @DisallowConcurrentExecution Anotasi memastikan serialisasi tugas
Tambahkan @DisAllowCurrentExecution Anotasi di FirstTask dan SecondTask masing -masing, dan hasil log adalah sebagai berikut:
Log A1 adalah sebagai berikut:
20180405 15:32:45 --- Mulai layanan pertama
20180405 15:32:51 --- Akhiri Layanan Pertama
20180405 15:32:51 --- Mulai layanan pertama
20180405 15:32:51 --- Mulai layanan kedua
20180405 15:32:57 ---- Akhir Layanan Pertama
20180405 15:32:57 --- Akhir SecondService
20180405 15:32:57 --- Mulai FirstService
20180405 15:32:57 --- Mulai layanan kedua
Log A2 adalah sebagai berikut:
20180405 15:32:45 --- Mulai layanan kedua
20180405 15:32:51 --- Akhiri SecondService
Mengamati log, Anda dapat menemukan bahwa tugas hanya akan memulai tugas baru setelah akhir, dan menyadari serialisasi tugas;
Meringkaskan
Artikel ini bertujuan untuk memiliki pemahaman intuitif tentang penjadwalan Spring+Quartz yang didistribusikan dan menyelesaikan masalah melalui penggunaan aktual. Tentu saja, mungkin ada banyak pertanyaan seperti bagaimana itu dijadwalkan, apa yang akan terjadi jika basis data digantung, dll., Dan lebih banyak pemahaman mendalam diperlukan.
Di atas adalah semua konten artikel ini. Saya berharap ini akan membantu untuk pembelajaran semua orang dan saya harap semua orang akan lebih mendukung wulin.com.