1. Principe de mise en œuvre de base de la planification des tâches en quartz
Quartz est un projet open source dans le domaine de la planification des tâches par Opensymphony, qui est entièrement basé sur la mise en œuvre de Java. En tant qu'excellent cadre de planification open source, Quartz a les fonctionnalités suivantes:
(1) des fonctions de planification puissantes, telles que la prise en charge d'une variété de méthodes de planification, peuvent répondre à divers besoins conventionnels et spéciaux;
(2) des méthodes d'application flexibles, telles que la prise en charge de plusieurs combinaisons de tâches et de planification, et de prendre en charge plusieurs méthodes de stockage de planification des données;
(3) Capacités de distribution et de regroupement, la terre cuite a encore amélioré ses fonctions d'origine après l'acquisition. Cet article s'ajoutera à cette partie.
1.1 Éléments centraux de quartz
Les éléments principaux de la planification des tâches de quartz sont: Scheduler-Task Scheduler, Trigger-Trigger et Job-task. où le déclencheur et le travail sont des métadonnées pour la planification des tâches, et le planificateur est le contrôleur qui effectue réellement la planification.
Le déclencheur est un élément utilisé pour définir l'heure de planification, c'est-à-dire, selon les règles de temps, la tâche est exécutée. Il existe quatre types de déclencheurs dans le quartz: SimpleTrigger, Cronttirgger, DateIntervaltrigger et Nthindeddaytrigger. Ces quatre déclencheurs peuvent répondre à la plupart des besoins des applications d'entreprise.
Le travail est utilisé pour représenter les tâches planifiées. Il existe principalement deux types d'emplois: les apatrides et l'état. Pour le même déclencheur, les travaux avec état ne peuvent pas être exécutés en parallèle. Ce n'est qu'après l'exécution de la tâche déclenchée par la dernière que la prochaine exécution peut être déclenchée. Le travail a deux attributs principaux: volatile et durabilité, où volatile signifie si la tâche est persistante pour le stockage de la base de données, tandis que la durabilité signifie si la tâche est conservée lorsqu'il n'y a pas d'association de déclenchement. Les deux sont persistés ou conservés lorsque la valeur est vraie. Un travail peut être associé à plusieurs déclencheurs, mais un déclencheur ne peut associer qu'un seul travail.
Scheduler est créé par Scheduler Factory: DirecSchedulerFactory ou StdscheDulerFactory. La deuxième usine, StdschedulerFactory, est utilisée plus fréquemment car DirectSchedulerFactory n'est pas assez pratique à utiliser, et de nombreux paramètres de codage manuel détaillé sont nécessaires. Il existe trois principaux types de planificateur: RemotembeanScheduler, Remotescheduler et Stdscheduler.
La relation entre les éléments centraux du quartz est illustrée à la figure 1.1:
Figure 1.1 Diagramme de la relation d'élément central
Vue de fil de quartz 1.2
Dans Quartz, il existe deux types de threads, des threads de planificateur de planificateur et des threads d'exécution des tâches, où les threads d'exécution des tâches utilisent généralement un pool de threads pour maintenir un groupe de threads.
Figure 1.2 Vue de filetage de quartz
Il y a deux threads principaux pour Scheduler: des threads qui effectuent une planification régulière et des threads qui exécutent Misfiredtrigger. Les sondages réguliers de filetage d'expédition tous sont stockés. S'il y a un déclencheur qui doit être déclenché, c'est-à-dire que le temps du déclencheur suivant a atteint, il obtient un thread inactif du pool de thread d'exécution de la tâche pour exécuter la tâche associée au déclencheur. Le fil de raté scanne tous les déclencheurs pour voir s'il y a un insignet. Si c'est le cas, il est géré séparément en fonction de la politique de raté (incendie maintenant ou attendez le prochain incendie).
1.3 Stockage de données de travail en quartz
Les déclencheurs et les emplois en quartz doivent être stockés avant de pouvoir être utilisés. Il existe deux méthodes de stockage dans Quartz: Ramjobstore et Jobstoresupport, où les magasins Ramjobstore sont déclencheurs et emplois en mémoire, tandis que les magasins d'emploi des magasins et des emplois dans la base de données basés sur JDBC. Ramjobstore a un accès très rapide, mais comme toutes les données seront perdues après l'arrêt du système, JobstoResUpport doit être utilisé dans les applications de cluster.
2. Principe de cluster de quartz 2.1 Architecture de cluster de quartz
Chaque nœud dans un cluster de quartz est une application de quartz indépendante, qui à son tour gère d'autres nœuds. Cela signifie que vous devez démarrer ou arrêter chaque nœud séparément. Dans le cluster de quartz, les nœuds de quartz indépendants ne communiquent pas avec un autre nœud ou nœud de gestion, mais perçoivent plutôt une autre application de quartz via la même table de base de données, comme le montre la figure 2.1.
Figure 2.1 Architecture de cluster de quartz
2.2 Tables de base de données liées au cluster en quartz
Étant donné que le cluster de quartz dépend de la base de données, il est nécessaire de créer d'abord la table de base de données Quartz. Le package de version Quartz comprend des scripts SQL pour toutes les plates-formes de base de données prises en charge. Ces scripts SQL sont stockés dans le répertoire <quartz_home> / docs / dbtables. La version 1.8.4 du quartz utilisée ici a un total de 12 tables. Le nombre de tables peut être différent dans différentes versions. La base de données est MySQL et utilise Tables_mysql.sql pour créer une table de base de données. Toutes les tableaux sont illustrés à la figure 2.2, et une brève introduction à ces tables est illustrée à la figure 2.3.
Figure 2.2 Tables générées dans Quartz 1.8.4 dans la base de données MySQL
Figure 2.3 Introduction au tableau de données de quartz
2.2.1 Tableau d'état du planificateur (QRTZ_SCHEDULER_STATE)
Description: Les informations sur l'instance du nœud dans le cluster, Quartz lit régulièrement les informations de ce tableau pour déterminer l'état actuel de chaque instance dans le cluster.
instance_name: le nom configuré par org.quartz.scheduler.instanceid dans le fichier de configuration. S'il est défini sur Auto, Quartz générera un nom basé sur le nom de la machine physique et l'heure actuelle.
Last_checkin_time: Dernière heure d'enregistrement
checkin_interval: heure d'intervalle d'enregistrement
2.2.2 Tableau d'association de déclencheurs et de tâches (QRTZ_FIRED_TRIGGERS)
Statut les informations sur l'état liées aux informations déclenchées de déclenchement et d'exécution du travail associé.
2.2.3 Tableau d'informations déclenchent (QRTZ_TRIGGERS)
Trigger_name: nom de déclenchement, l'utilisateur peut personnaliser le nom à volonté, aucune exigence forcée
Trigger_Group: le nom du groupe de déclenchement, que l'utilisateur peut personnaliser à volonté, et il n'y a pas d'exigence forcée.
Job_name: clé étrangère de QRTZ_JOB_DETAILS Table Job_name
job_group: QRTZ_JOB_DETAILS TABLE PLAG_GROUP Clé étrangère
Trigger_State: l'état de déclenchement actuel est défini sur acquis. S'il est défini à l'attente, le travail ne se déclenchera pas.
Trigger_cron: Type de déclenchement, en utilisant l'expression cron
2.2.4 Table Détails Tableau (QRTZ_JOB_DETAILS)
Remarque: enregistrez les détails du travail, le tableau doit être initialisé par l'utilisateur en fonction de la situation réelle
Job_name: le nom du travail dans le cluster. L'utilisateur peut personnaliser le nom à volonté, sans aucune exigence forcée.
Job_group: le nom du groupe auquel le travail appartient au cluster, qui est personnalisé par l'utilisateur à volonté, et il n'y a pas d'exigences forcées.
job_class_name: le nom complet du package de la classe d'implémentation du travail dans le cluster. Quartz trouve la classe d'emploi basée sur ce chemin vers ClassPath.
IS_DURY: Que ce soit pour persister, définir cette propriété sur 1, Quartz persistera le travail dans la base de données
Job_data: un champ blob qui stocke a persisté des objets de travail.
2.2.5 Tableau d'informations d'autorisation (QRTZ_LOCKS)
Remarque: il y a une initialisation DML correspondante dans TABLES_ORACLE.SQL, comme le montre la figure 2.4.
Figure 2.4 Informations d'initialisation dans le tableau des informations d'autorisation de quartz
2.3 Processus de démarrage du planificateur de quartz dans le cluster
Le planificateur de quartz lui-même ne remarque pas qu'il est en grappe, et seul le JDBC Jobstore configuré pour le planificateur le saura. Lorsque le planificateur de quartz commence, il appelle la méthode ScheduleStarted () du Jobstore, qui indique au planificateur Jobstore qu'il a commencé. La méthode ScheduleStarted () est implémentée dans la classe JobStoresupport. La classe JobStoresupport détermine si l'instance du planificateur participe au cluster en fonction des paramètres du fichier quartz.properties. Si le cluster est configuré, une instance d'une nouvelle classe ClusterManager sera créée, initialisée et démarrée. ClusterManager est une classe en ligne dans la classe JobStoresupport, héritant de java.lang.thread, il s'exécute régulièrement et exécute des fonctions d'enregistrement sur l'instance du planificateur. Le planificateur doit également vérifier si d'autres nœuds de cluster ont échoué. Le cycle d'exécution de l'opération d'enregistrement est configuré dans Quartz.properties.
2.4 Détection d'un nœud de planificateur échoué
Lorsqu'une instance de planificateur effectue un enregistrement, il vérifie si d'autres instances de planificateur n'ont pas été enregistrées au moment où elles s'y attendaient. Ceci est déterminé en vérifiant si la valeur du planificateur enregistré dans la colonne Last_chedk_time dans la table Scheduler_State est plus tôt que org.quartz.jobstore.clustercheckinInterval. Si un ou plusieurs nœuds n'ont pas été enregistrés à un moment prédéterminé, le planificateur de course suppose qu'ils ont échoué.
2.5 Récupération des emplois à partir d'instances ratées
Lorsqu'une instance Sheduler échoue lors de l'exécution d'un emploi, il est possible qu'une autre instance de planificateur de travail prenne le travail et l'exécute à nouveau. Pour réaliser ce comportement, la propriété de récupération de travail configurée dans l'objet JobDetail doit être définie sur true (job.setRequestSrecovery (true)). Si la propriété récupérable est définie sur FALSE (par défaut est faux), il ne remettra pas lorsqu'un planificateur ne parviendra pas à exécuter le travail; Il sera déclenché par une autre instance de planificateur au prochain temps de déclenchement. La rapidité avec laquelle l'instance du planificateur peut être détectée après une défaillance dépend de l'intervalle d'enregistrement de chaque planificateur (c'est-à-dire org.quartz.jobstore.clustercheckinInterval mentionné en 2.3).
3. Instance de cluster de quartz (quartz + printemps)
3.1 Spring incompatible avec les problèmes de quartz
Spring ne prend plus en charge le quartz depuis 2.0.2. Plus précisément, lorsque Quartz + Spring instancie la tâche de Quartz dans la base de données, une erreur sérialisable se produira:
<bean id = "jobtask"> <propriété name = "cibleObject"> <ref bean = "quartzjob" /> </ propriété> <propriété name = "TargetMethod"> <value> Exécuter </value> </ / propriété> </bEAN>
La méthode MethodinVoking dans la classe MethodinVokJobDetAtailFactoryBean ne prend pas en charge la sérialisation, elle lancera donc une erreur lors de la sérialisation de la tâche du quartz dans la base de données.
Tout d'abord, résolvez le problème de MethodinVokingJobDetailFactoryBean. Sans modifier le code source Spring, vous pouvez éviter d'utiliser cette classe et appeler directement JobDetail. Cependant, l'utilisation de l'implémentation de Jobdetail vous oblige à implémenter la logique de Pothodinvoking par vous-même. Vous pouvez utiliser les propriétés JobClass et JobDataAmmap de Jobdetail pour personnaliser une usine (gestionnaire) pour atteindre le même objectif. Par exemple, dans cet exemple, un nouveau MyDetailquartzJobbean est créé pour implémenter cette fonction.
3.2 Fichier MyDetailquartzJobbean.java
package org.lxh.mvc.jobbean; import java.lang.reflect.method; import org.apache.commons.logging.log; import org.apache.commons.logging.logfactory; import org.quartz.jobexecut org.springframework.context.applicationContext; import org.springframework.scheduling.quartz.quartzjobbean; public class MyDetailquartzJobbean étend QuartzJobbean {Protected Final Logger = logFactory.getLog (getClass ()); chaîne privée TargetObject; chaîne privée TargetMethod; Application PrivateContext CTX; Protected void executeInternal (JobExecutionContext Context) lève JobExECUTURICE {try {logger.info ("exécuter [" + TargetObject + "] à la fois >>>>>"); Objet oargetObject = ctx.getBean (TargetObject); Méthode m = null; try {m = oargetObject.getClass (). getMethod (TargetMethod, new class [] {}); M.Invoke (oargetObject, nouvel objet [] {}); } catch (SecurityException e) {logger.Error (e); } catch (NosuchMethodexception e) {logger.Error (e); }} catch (exception e) {lancer un nouveau jobExecutionException (e); }} public void setApplicationContext (applicationContext ApplicationContext) {this.ctx = applicationContext; } public void SettRargetObject (String TargetObject) {this.targetObject = TargetObject; } public void SettargetMethod (String TargetMethod) {this.targetMethod = TargetMethod; }}3.3 Classe de mise en œuvre de l'emploi réel
Dans la classe de test, la fonction d'impression de l'heure actuelle du système est simplement implémentée.
package org.lxh.mvc.job; import java.io.serializable; import java.util.date; import org.apache.commons.logging.log; import org.apache.commons.logging.logfactory; public class test implémente serializable {private logger = logfactory.getlog (test.class); Final statique privé long SerialVersionUID = -2073310586499744415L; public void execute () {date date = new Date (); System.out.println (date.tolocalestring ()); }}3.4 Configurer le fichier quartz.xml
<bean id = "test" scope = "Prototype"> </ bean> <bean id = "testJobtask"> <propriété name = "jobclass"> <value> org.lxh.mvc.jobbean.mydetailquartzjobbean </value> </ propriété> <propriété name = "jobdataasmap"> <map> <entrée key = "Targetobject" key = "TargetMethod" value = "exécuter" /> </ map> </ propriété> </ bean> <bean name = "testTrigger"> <propriété name = "jobdetail" ref = "TestJobtask" /> <propriété name = "Cronexpression" value = "0/1 * * * *?" /> </ bean> <bean id = "QuartzScheduler"> <propriété name = "configLocation" value = "classpath: quartz.properties" /> <propriété name = "Triggers"> <s list> <ref bean = "testTright" /> </ list> </ propriété> <propriété name = "ApplicationConTScheduerContextKe
3.5 Test
Le code et la configuration de Servera et ServerB sont exactement les mêmes. Démarrez d'abord Servera, puis démarrez ServerB. Une fois le serveur fermé, ServerB surveillera son arrêt et reprendra le travail qui s'exécute sur Servera et continuera l'exécution.
4. Instance de cluster de quartz (quartz unique)
Bien que nous ayons implémenté la configuration du cluster de Spring + Quartz, il n'est toujours pas recommandé d'utiliser cette méthode en raison des problèmes de compatibilité entre le printemps et le quartz. Dans cette section, nous avons implémenté un cluster configuré séparément avec Quartz, qui est simple et stable par rapport au Spring + Quartz.
4.1 Structure d'ingénierie
Nous utilisons le quartz seul pour implémenter ses fonctions de cluster, sa structure de code et ses packages JAR tiers requis comme indiqué dans la figure 3.1. Parmi eux, la version MySQL: 5.1.52, et MySQL Driver Version: MySQL-Connector-Java-5.1.5-Bin.jar (pour 5.1.52, il est recommandé d'utiliser cette version du pilote car il existe un bogue en quartz qu'il ne peut pas fonctionner normalement lorsqu'il est combiné avec certains pilotes MySQL).
Figure 4.1 Structure d'ingénierie du cluster de quartz et packages de pot tiers requis
Parmi eux, Quartz.properties se trouve le fichier de configuration du quartz et placé dans le répertoire SRC. S'il n'y a pas de tel fichier, Quartz chargera automatiquement le fichier quartz.properties dans le package JAR; SimpleRecoveryJob.java et SimpleRecoveryStatefulJob.java sont deux emplois; ClusterExample.java écrit des informations de planification, le déclenchement du mécanisme et les fonctions principales de test correspondantes.
4.2 Fichier de configuration Quartz.properties
Le nom de fichier par défaut Quartz.properties est utilisé pour activer la fonctionnalité de cluster en définissant la propriété "org.quartz.jobstore.isclustered" sur "true". Chaque instance du cluster doit avoir un "ID d'instance" unique ("Org.quartz.scheduler.instanceId" Property), mais il doit avoir le même "nom d'instance de planificateur" ("org.quartz.scheduler.instanceName"), ce qui signifie que chaque instance dans le cluster doit utiliser le même fichier de configuration Quartz.Properties. À l'exception des exceptions suivantes, le contenu du fichier de configuration doit être le même:
un. Taille de la piscine de filetage.
né Différents valeurs d'attribut "org.quartz.scheduler.instanceId" (il suffit de définir "Auto").
# =======================================================================. ==========================================================================. ==========================================================================. ==========================================================================. ==========================================================================. ==========================================================================. ==========================================================================. ==========================================================================. AUTO#============================================================================================== ========================================================================================================================. org.quartz.jobstore.impl.jdbcjobstore.jobstoretxorg.quartz.jobstore.driverdelegateclass = org.quartz.impl.jdbcjobstore.stdjdbcdelegateorg.quartz.jobstore.tableprefix = Qrtz_org.quartz.jobstore.isclustered = trueorg.quartz.jobstore.clustercheckinInterval = 10000 org.quartz.jobstore.datasource = Myds # ======================================================================================================================. =======================================================================================================================. =======================================================================================================================. =======================================================================================================================. # =======================================================================================================. com.mysql.jdbc.driverorg.quartz.datasource.myds.url = jdbc: mysql: //192.168.31.18: 3306 / test? useunicode = true & caractères. rootorg.quartz.datasource.myds.password = 123456org.quartz.datasource.myds.maxconnections = 30 # ===================================================================. =====================================================================. =====================================================================. =====================================================================. =====================================================================. =====================================================================. =====================================================================. =====================================================================. org.quartz.simpl.simplethReadpoolorg.quartz.threadpool.threadCount = 5org.quartz.threadpool.threadpriority = 5org.quartz.threadpool.threadsinHeritContextClassLoDerofinitializingThread =
4.3 Fichier ClusterExample.java
Cluster de packages; import java.util.date; import org.quartz.jobdetail; import org.quartz.scheduler; import org.quartz.schedulerfactory; import org.quartz.simpletrgerg; import org.quartz.impl.stdschedulerfactory) cluster de classe publique {corduler corduler) clurexample {corduler) lance l'exception {System.out.println ("**** Suppression des travaux / déclencheurs existants *****"); // Unschedule Jobs String [] Groupes = InscheDuler.GetTriggerGroupNames (); for (int i = 0; i <groupes.length; i ++) {String [] names = InscheDuler.getTriggerNames (groupes [i]); for (int j = 0; j <names.length; j ++) {InscheDuler.unscheduleJob (noms [j], groupes [i]); }} // supprimer des groupes de travaux = InsCheDuler.GetJobGroupNames (); for (int i = 0; i <groupes.length; i ++) {String [] names = inscheduler.getJobNames (groupes [i]); for (int j = 0; j <names.length; j ++) {InscheDuler.deleteJob (noms [j], groupes [i]); }}} public void run (booléen inclutjobs, booléen InscheduleJobs) lève une exception {// nous devons d'abord obtenir une référence à un planificateur schedulerfactory sf = new stdschedulerfactory (); Scheduler sched = sf.getscheduler (); if (inclusarjobs) {Cleanup (sched); } System.out.println ("---------------------------"); if (InscheduleJobs) { System.out.println("------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Réexécuter ce travail si elle était en cours lorsque // le planificateur est tombé en baisse ... AT: "+ Trigger.getNextFiretime () +" et répétez: "+ Trigger.GetRepeatCount () +" Times, chaque "+ Trigger.getRepeatInterval () / 1000 +" Seconds "); Sched.scheduleJob (Job, Trigger); Count ++; Job = New JobDetail (" Job_ "+ Count, Scardid, Simplat Scheduleuse pour réexécuter ce travail si elle a été en cours lorsque // le planificateur est tombé ... AT: "+ Trigger.getNextFireTime () +" et répétez: "+ Trigger.getRepeatCount () +" fois, chaque "+ Trigger.getRepeatInterval () / 1000 +" Seconds "); sched.scheduleJob (travail, Trigger);} // Les travaux ne commencent pas le feu avant de démarrer () a été appelé ... System.out.println ("------------------------------------"); System.out.println ("----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 1000l);} catch (exception e) {} System.out.println ("----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Args.length; i ++) {if (args [i] .equalsignorecase ("clearjobs")) {clearjobs = true; }}4.4 SimpleRecoveryJob.java
Cluster de packages; import java.io.serializable; import java.util.date; import org.apache.commons.logging.log; import org.apache.commons.logging.logfactory; import org.quartz.job; import org.quartz.jobexecutex Que vous souhaitez exécuter à plusieurs reprises, écrivez le code pertinent dans la méthode EXECUTE, la prémisse est: implémenter l'interface de travail // Quant au moment où la classe SimpleJob est instanciée et lorsque la méthode d'exécution est appelée, nous n'avons pas besoin de y prêter attention, et de le laisser à la classe de quartzpublique SimpleecveryJob implémente le travail, sérialisable {STATIQUE privé _log = Logfactory.getLog (SimpleRecoveryJob.class); public SimpleRecoveryJob () {} public void execute (JobExECUTCUTEXT Context) lève JobExEcutionException {// Ce travail imprime simplement le nom du travail et le moment où le travail exécute String JobName = context.getJobDetail (). GetfullName (); System.out.println ("JOB 111111111111111 SimpleCoveryJob dit:" + JobName + "Exécution à" + new Date ()); }}4.5 Résultats de l'opération
La configuration et le code du serveur A et du serveur B sont exactement les mêmes. Méthode d'exécution: exécutez ClusterExample.java sur n'importe quel hôte, ajoutez la tâche au calendrier et observez les résultats d'exécution:
Exécuter Servera, les résultats sont présentés à la figure 4.2.
Figure 4.2 Résultat de l'opération du serveur 1
Après avoir allumé ServerB, la sortie de Servera et ServerB est illustrée aux figures 4.3 et 4.4.
Figure 4.3 Servera Exécution du résultat 2
Figure 4.4 Résultat de l'opération du serveur 1
Il peut être vu à partir des figures 4.3 et 4.4 qu'après l'allumage du serveurb, le système réalise automatiquement la responsabilité de l'équilibre et ServerB reprend Job1. Après avoir arrêté Servera, les résultats en cours d'exécution de ServerB sont illustrés à la figure 4.5.
Figure 4.5 Résultat de l'opération du serveur 2
Comme on peut le voir sur la figure 4.5, ServerB peut détecter que Servera est perdu, prendre en charge la tâche Job2 et perdre Servera à la Job2 qui doit être exécutée pendant cette période d'exception.
5. Choses à noter
5.1 Problème de synchronisation du temps
Le quartz ne se soucie pas vraiment de savoir si vous exécutez des nœuds sur les mêmes machines ou différentes. Lorsqu'un cluster est placé sur différentes machines, il est appelé un cluster horizontal. Lorsqu'un nœud fonctionne sur la même machine, il est appelé un cluster vertical. Pour les grappes verticales, il y a un problème de point de défaillance unique. Ceci est inacceptable pour les applications à haute disponibilité, car une fois que la machine se bloque, tous les nœuds sont terminés. Pour les grappes horizontales, il y a un problème de synchronisation temporelle.
Le nœud utilise un horodatage pour informer d'autres instances de sa dernière heure d'enregistrement. Si l'horloge du nœud est définie à l'heure future, le planificateur de course ne se rendra plus compte que le nœud est tombé. D'un autre côté, si l'horloge d'un nœud est réglé sur le temps passé, l'autre nœud déterminera peut-être que le nœud est tombé et essaie de prendre son travail et de rediffusion. Le moyen le plus simple de synchroniser une horloge informatique est d'utiliser un serveur de temps Internet.
5.2 Le problème des nœuds en concurrence pour les emplois
Étant donné que Quartz utilise un algorithme d'équilibrage de charge aléatoire, le travail est exécuté par différentes instances de manière aléatoire. Le site officiel de Quartz a mentionné qu'à l'heure actuelle, il n'y a pas de méthode pour attribuer (épingler) un travail à un nœud spécifique dans le cluster.
5.3 Issue pour obtenir la liste des travaux à partir du cluster
Actuellement, si vous n'entrez pas directement la requête de la base de données, il n'y a pas de moyen simple d'obtenir une liste de tous les travaux d'exécution du cluster. La demande d'une instance de planificateur n'obtiendra qu'une liste de travaux exécutés sur cette instance. Le site officiel de Quartz recommande de pouvoir obtenir toutes les informations de travail de la table correspondante en écrivant un code JDBC pour accéder à la base de données.
Résumer
Ce qui précède est l'intégralité du contenu de cet article. J'espère que le contenu de cet article a une certaine valeur de référence pour l'étude ou le travail de chacun. Si vous avez des questions, vous pouvez laisser un message pour communiquer. Merci pour votre soutien à wulin.com.