LTS (light-task-scheduler) est principalement utilisé pour résoudre les problèmes de planification de tâches distribuées et prend en charge les tâches en temps réel, les tâches planifiées et les tâches Cron. Il présente une bonne évolutivité, évolutivité, robustesse et stabilité et est utilisé par de nombreuses entreprises. Nous espérons également que les passionnés de l'open source pourront contribuer ensemble.
Adresse Github : https://github.com/ltsopensource/light-task-scheduler
adresse oschina : http://git.oschina.net/hugui/light-task-scheduler
Exemples : https://github.com/ltsopensource/lts-examples
Adresse du document (en cours de mise à jour, celle-ci prévaudra ultérieurement) : https://www.gitbook.com/book/qq254963746/lts/details
Les deux adresses seront mises à jour simultanément. Si vous êtes intéressé, merci de rejoindre le groupe QQ : 109500214 (mot de passe du groupe : hello world) pour discuter et améliorer ensemble. Plus il y aura de personnes qui le soutiendront, plus il y aura de motivation pour le mettre à jour. Si vous le souhaitez, n'oubliez pas de mettre une étoile dans le coin supérieur droit.
LTS possède principalement les quatre types de nœuds suivants :
Les nœuds JobClient, JobTracker et TaskTracker sont tous无状态
. Plusieurs peuvent être déployés et supprimés dynamiquement pour obtenir un équilibrage de charge et une plus grande capacité de charge, et le framework utilise la stratégie FailStore pour que LTS ait une bonne tolérance aux pannes.
Le centre d'enregistrement LTS fournit plusieurs implémentations (Zookeeper, redis, etc.). Le centre d'enregistrement expose les informations sur les nœuds et élit les maîtres. (Mongo ou Mysql) stocke les files d'attente de tâches et les journaux d'exécution des tâches, netty ou mina effectue la communication sous-jacente et fournit plusieurs méthodes de sérialisation telles que fastjson, hessian2, java, etc.
LTS prend en charge les types de tâches :
Prend en charge la modification dynamique des paramètres de tâche, du temps d'exécution des tâches et d'autres paramètres, prend en charge l'ajout dynamique de tâches en arrière-plan, prend en charge la suspension des tâches Cron, prend en charge l'arrêt manuel des tâches en exécution (conditionnel), prend en charge les statistiques de surveillance des tâches, prend en charge la surveillance de l'exécution des tâches de chaque nœud. , Surveillance JVM, etc.
La figure ci-dessous est un processus standard d'exécution de tâches en temps réel.
Actuellement, le backend dispose d'une fonction d'authentification simple fournie par ztajy. Le nom d'utilisateur et le mot de passe sont dans auth.cfg et peuvent être modifiés par l'utilisateur.
LTS n'a pas du tout besoin du framework Spring, mais étant donné que de nombreux projets d'utilisateurs utilisent le framework Spring, LTS fournit également une prise en charge de Spring, y compris XML et les annotations, en introduisant simplement lts-spring.jar
.
Un enregistreur d'entreprise est fourni du côté de TaskTracker pour être utilisé par les applications. Grâce à cet enregistreur d'entreprise, les journaux d'entreprise peuvent être soumis à JobTracker. Ces journaux d'entreprise peuvent être concaténés par ID de tâche et l'exécution de la tâche peut être visualisée en temps réel. dans le calendrier LTS-Admin.
L'extension SPI peut atteindre zéro intrusion. Il suffit d'implémenter l'interface correspondante et elle peut être utilisée par LTS. Les interfaces d'extension actuellement ouvertes sont.
Lorsque le TaskTracker qui exécute la tâche plante, le JobTracker allouera immédiatement toutes les tâches assignées au TaskTracker arrêté à d'autres nœuds TaskTracker normaux pour exécution.
La surveillance des ressources, la surveillance des tâches, etc. peuvent être effectuées sur les nœuds JobTracker et TaskTracker, et peuvent être visualisées en temps réel dans l'arrière-plan de gestion LTS-Admin pour effectuer une allocation raisonnable des ressources.
Le framework LTS prend en charge quatre résultats d'exécution, EXECUTE_SUCCESS
, EXECUTE_FAILED
, EXECUTE_LATER
et EXECUTE_EXCEPTION
, et adopte les mécanismes de traitement correspondants pour chaque résultat, comme une nouvelle tentative.
Le mécanisme FailStore est utilisé pour la tolérance aux pannes des nœuds. Fail And Store n'affectera pas le fonctionnement de l'application actuelle en raison de l'instabilité de la communication à distance. Pour des instructions spécifiques à FailStore, veuillez vous référer aux instructions FailStore dans la description du concept.
Le projet est principalement construit à l'aide de maven et fournit actuellement un package de scripts shell. Dépendances d'environnement : Java(jdk1.6+)
Maven
L'utilisation des utilisateurs est généralement divisée en deux types :
Vous pouvez télécharger le package lts jar vers l'entrepôt local via la commande maven. Ajoutez le référentiel correspondant dans le pom.xml parent et téléchargez-le avec la commande de déploiement. Pour les méthodes de citation spécifiques, veuillez vous référer aux exemples dans lts.
Chaque module de lts doit être regroupé dans un package jar distinct et tous les packages de dépendances lts doivent être importés. Pour une référence spécifique aux packages jar, vous pouvez vous référer aux exemples dans lts.
Deux scripts de version sont fournis (cmd)windows
et (shell)linux
pour la compilation et le déploiement :
L'exécution du script sh build.sh
ou build.cmd
dans le répertoire racine générera le dossier lts-{version}-bin
dans dist
.
Voici sa structure de répertoires, dans laquelle le répertoire bin contient principalement les scripts de démarrage de JobTracker et LTS-Admin. jobtracker
contient le fichier de configuration de JobTracker et le package jar qui doit être utilisé est le package war et le fichier de configuration liés à lts-admin
-Admin. Structure de fichier de lts-{version}-bin
-- lts - $ { version }- bin
|-- bin
| |-- jobtracker . cmd
| |-- jobtracker . sh
| |-- lts - admin . cmd
| |-- lts - admin . sh
| |-- lts - monitor . cmd
| |-- lts - monitor . sh
| |-- tasktracker . sh
|-- conf
| |-- log4j . properties
| |-- lts - admin . cfg
| |-- lts - monitor . cfg
| |-- readme . txt
| |-- tasktracker . cfg
| |-- zoo
| |-- jobtracker . cfg
| |-- log4j . properties
| |-- lts - monitor . cfg
|-- lib
| |-- *. jar
|-- war
|-- jetty
| |-- lib
| |-- *. jar
|-- lts - admin . war
conf/zoo
, puis exécutez sh jobtracker.sh zoo start
. Si vous souhaitez démarrer deux nœuds JobTracker, vous devez alors copier un zoo, par exemple, nommez-le. zoo2
, modifiez le fichier de configuration sous zoo2
, puis exécutez sh jobtracker.sh zoo2 start
. Le journal jobtracker-zoo.out
est généré dans le dossier des journaux.conf/lts-monitor.cfg
et conf/lts-admin.cfg
, puis exécutez le script sh lts-admin.sh
ou lts-admin.cmd
sous bin
. lts-admin.out
sera généré dans le dossier des journaux. Si le démarrage réussit, l'adresse d'accès sera imprimée dans le journal. Les utilisateurs pourront accéder via cette adresse d'accès. Les packages jar qui doivent être importés dans lts incluent lts-jobclient-{version}.jar
, lts-core-{version}.jar
et d'autres jars dépendants tiers.
JobClient jobClient = new RetryJobClient ();
jobClient . setNodeGroup ( "test_jobClient" );
jobClient . setClusterName ( "test_cluster" );
jobClient . setRegistryAddress ( "zookeeper://127.0.0.1:2181" );
jobClient . start ();
// 提交任务
Job job = new Job ();
job . setTaskId ( "3213213123" );
job . setParam ( "shopId" , "11111" );
job . setTaskTrackerNodeGroup ( "test_trade_TaskTracker" );
// job.setCronExpression("0 0/1 * * * ?"); // 支持 cronExpression表达式
// job.setTriggerTime(new Date()); // 支持指定时间执行
Response response = jobClient . submitJob ( job );
< bean id = "jobClient" class = "com.github.ltsopensource.spring.JobClientFactoryBean" >
< property name = "clusterName" value = "test_cluster" />
< property name = "registryAddress" value = "zookeeper://127.0.0.1:2181" />
< property name = "nodeGroup" value = "test_jobClient" />
< property name = "masterChangeListeners" >
< list >
< bean class = "com.github.ltsopensource.example.support.MasterChangeListenerImpl" />
</ list >
</ property >
< property name = "jobFinishedHandler" >
< bean class = "com.github.ltsopensource.example.support.JobFinishedHandlerImpl" />
</ property >
< property name = "configs" >
< props >
<!-- 参数 -->
< prop key = "job.fail.store" > leveldb </ prop >
</ props >
</ property >
</ bean >
@ Configuration
public class LTSSpringConfig {
@ Bean ( name = "jobClient" )
public JobClient getJobClient () throws Exception {
JobClientFactoryBean factoryBean = new JobClientFactoryBean ();
factoryBean . setClusterName ( "test_cluster" );
factoryBean . setRegistryAddress ( "zookeeper://127.0.0.1:2181" );
factoryBean . setNodeGroup ( "test_jobClient" );
factoryBean . setMasterChangeListeners ( new MasterChangeListener []{
new MasterChangeListenerImpl ()
});
Properties configs = new Properties ();
configs . setProperty ( "job.fail.store" , "leveldb" );
factoryBean . setConfigs ( configs );
factoryBean . afterPropertiesSet ();
return factoryBean . getObject ();
}
}
Les packages jar qui doivent être importés dans lts incluent lts-tasktracker-{version}.jar
, lts-core-{version}.jar
et d'autres jars dépendants tiers.
public class MyJobRunner implements JobRunner {
@ Override
public Result run ( JobContext jobContext ) throws Throwable {
try {
// TODO 业务逻辑
// 会发送到 LTS (JobTracker上)
jobContext . getBizLogger (). info ( "测试,业务日志啊啊啊啊啊" );
} catch ( Exception e ) {
return new Result ( Action . EXECUTE_FAILED , e . getMessage ());
}
return new Result ( Action . EXECUTE_SUCCESS , "执行成功了,哈哈" );
}
}
TaskTracker taskTracker = new TaskTracker ();
taskTracker . setJobRunnerClass ( MyJobRunner . class );
taskTracker . setRegistryAddress ( "zookeeper://127.0.0.1:2181" );
taskTracker . setNodeGroup ( "test_trade_TaskTracker" );
taskTracker . setClusterName ( "test_cluster" );
taskTracker . setWorkThreads ( 20 );
taskTracker . start ();
< bean id = "taskTracker" class = "com.github.ltsopensource.spring.TaskTrackerAnnotationFactoryBean" init - method = "start" >
< property name = "jobRunnerClass" value = "com.github.ltsopensource.example.support.MyJobRunner" />
< property name = "bizLoggerLevel" value = "INFO" />
< property name = "clusterName" value = "test_cluster" />
< property name = "registryAddress" value = "zookeeper://127.0.0.1:2181" />
< property name = "nodeGroup" value = "test_trade_TaskTracker" />
< property name = "workThreads" value = "20" />
< property name = "masterChangeListeners" >
< list >
< bean class = "com.github.ltsopensource.example.support.MasterChangeListenerImpl" />
</ list >
</ property >
< property name = "configs" >
< props >
< prop key = "job.fail.store" > leveldb </ prop >
</ props >
</ property >
</ bean >
@ Configuration
public class LTSSpringConfig implements ApplicationContextAware {
private ApplicationContext applicationContext ;
@ Override
public void setApplicationContext ( ApplicationContext applicationContext ) throws BeansException {
this . applicationContext = applicationContext ;
}
@ Bean ( name = "taskTracker" )
public TaskTracker getTaskTracker () throws Exception {
TaskTrackerAnnotationFactoryBean factoryBean = new TaskTrackerAnnotationFactoryBean ();
factoryBean . setApplicationContext ( applicationContext );
factoryBean . setClusterName ( "test_cluster" );
factoryBean . setJobRunnerClass ( MyJobRunner . class );
factoryBean . setNodeGroup ( "test_trade_TaskTracker" );
factoryBean . setBizLoggerLevel ( "INFO" );
factoryBean . setRegistryAddress ( "zookeeper://127.0.0.1:2181" );
factoryBean . setMasterChangeListeners ( new MasterChangeListener []{
new MasterChangeListenerImpl ()
});
factoryBean . setWorkThreads ( 20 );
Properties configs = new Properties ();
configs . setProperty ( "job.fail.store" , "leveldb" );
factoryBean . setConfigs ( configs );
factoryBean . afterPropertiesSet ();
// factoryBean.start();
return factoryBean . getObject ();
}
}
Description des paramètres
Généralement, une seule instance de JobClient est nécessaire dans une JVM. Ne créez pas une nouvelle instance de JobClient pour chaque tâche. Cela gaspillerait considérablement des ressources, car un JobClient peut soumettre plusieurs tâches. La même JVM essaie généralement de maintenir une seule instance de TaskTracker. S'il y a plusieurs instances, cela peut entraîner un gaspillage de ressources. Lorsque vous rencontrez un TaskTracker qui doit exécuter plusieurs tâches, veuillez vous référer à « Un TaskTracker effectue plusieurs tâches » ci-dessous.
Parfois, les scénarios commerciaux nécessitent l'exécution de plusieurs tâches. Certaines personnes peuvent se demander si chaque type de tâche nécessite l'exécution d'un TaskTracker. Ma réponse est non. Si vous êtes dans une JVM, il est préférable d'utiliser un TaskTracker pour exécuter plusieurs tâches, car utiliser plusieurs instances de TaskTracker dans une JVM est un gaspillage de ressources (bien sûr, lorsque vous avez un grand nombre de certaines tâches). , vous pouvez utiliser un nœud TaskTracker distinct pour exécuter cette tâche). Alors, comment pouvons-nous implémenter un TaskTracker pour effectuer plusieurs tâches ? Vous trouverez ci-dessous l'exemple de référence que j'ai donné.
/**
* 总入口,在 taskTracker.setJobRunnerClass(JobRunnerDispatcher.class)
* JobClient 提交 任务时指定 Job 类型 job.setParam("type", "aType")
*/
public class JobRunnerDispatcher implements JobRunner {
private static final ConcurrentHashMap < String /*type*/ , JobRunner >
JOB_RUNNER_MAP = new ConcurrentHashMap < String , JobRunner >();
static {
JOB_RUNNER_MAP . put ( "aType" , new JobRunnerA ()); // 也可以从Spring中拿
JOB_RUNNER_MAP . put ( "bType" , new JobRunnerB ());
}
@ Override
public Result run ( JobContext jobContext ) throws Throwable {
Job job = jobContext . getJob ();
String type = job . getParam ( "type" );
return JOB_RUNNER_MAP . get ( type ). run ( job );
}
}
class JobRunnerA implements JobRunner {
@ Override
public Result run ( JobContext jobContext ) throws Throwable {
// TODO A类型Job的逻辑
return null ;
}
}
class JobRunnerB implements JobRunner {
@ Override
public Result run ( JobContext jobContext ) throws Throwable {
// TODO B类型Job的逻辑
return null ;
}
}
Généralement, lors de l'écriture de TaskTracker, vous devez uniquement tester si la logique d'implémentation de JobRunner est correcte, mais vous ne souhaitez pas démarrer LTS pour des tests à distance. Pour faciliter les tests, LTS fournit la méthode de test des raccourcis de JobRunner. Intégrez simplement com.github.ltsopensource.tasktracker.runner.JobRunnerTester
dans votre propre classe de test et implémentez initContext
et newJobRunner
. Comme l'exemple dans lts-examples :
public class TestJobRunnerTester extends JobRunnerTester {
public static void main ( String [] args ) throws Throwable {
// Mock Job 数据
Job job = new Job ();
job . setTaskId ( "2313213" );
JobContext jobContext = new JobContext ();
jobContext . setJob ( job );
JobExtInfo jobExtInfo = new JobExtInfo ();
jobExtInfo . setRetry ( false );
jobContext . setJobExtInfo ( jobExtInfo );
// 运行测试
TestJobRunnerTester tester = new TestJobRunnerTester ();
Result result = tester . run ( jobContext );
System . out . println ( JSON . toJSONString ( result ));
}
@ Override
protected void initContext () {
// TODO 初始化Spring容器
}
@ Override
protected JobRunner newJobRunner () {
return new TestJobRunner ();
}
}
Pour les tâches Cron de Quartz, il vous suffit d'ajouter du code à la configuration Spring pour vous connecter à la plateforme LTS.
< bean class = " com.github.ltsopensource.spring.quartz.QuartzLTSProxyBean " >
< property name = " clusterName " value = " test_cluster " />
< property name = " registryAddress " value = " zookeeper://127.0.0.1:2181 " />
< property name = " nodeGroup " value = " quartz_test_group " />
</ bean >
@ SpringBootApplication
@ EnableJobTracker // 启动JobTracker
@ EnableJobClient // 启动JobClient
@ EnableTaskTracker // 启动TaskTracker
@ EnableMonitor // 启动Monitor
public class Application {
public static void main ( String [] args ) {
SpringApplication . run ( Application . class , args );
}
}
Il ne reste plus qu'à ajouter la configuration correspondante dans application.properties. Pour plus de détails, voir l'exemple sous com.github.ltsopensource.examples.springboot
dans lts-example.
Lorsque la machine dispose de deux cartes réseau sur le réseau interne, parfois, si l'utilisateur souhaite que le trafic LTS passe par la carte réseau externe, il doit alors modifier l'adresse de mappage du nom d'hôte en adresse de la carte réseau externe dans l'hôte. il en va de même pour le réseau interne.
Si l'ID du nœud est défini au démarrage du nœud, LTS définira un UUID comme ID de nœud par défaut. La lisibilité sera mauvaise, mais l'unicité de chaque nœud peut être garantie si l'utilisateur peut garantir l'unicité du nœud. ID par lui-même, il peut setIdentity
pour définir, par exemple, si chaque nœud est déployé sur une machine (une machine virtuelle), alors l'identité peut être définie sur le nom d'hôte
Prise en charge des extensions SPI pour JobLogger, JobQueue, etc.
Voir le numéro 389
L'expérience professionnelle est supérieure à trois ans
Exigences de formationBaccalauréat
Niveau d'attente P6 (ingénieur Java senior)/P7 (expert technique)
Description de l'emploi
La plate-forme d'adhésion est responsable du système d'utilisateurs du groupe Alibaba, répond aux besoins des utilisateurs de divers secteurs d'activité au sein du groupe et prend en charge les canaux d'utilisateurs et d'affaires de la coopération externe du groupe. Y compris la connexion et l'autorisation des utilisateurs, le système de session, l'enregistrement, la gestion des comptes, la sécurité des comptes et d'autres fonctions à chaque extrémité, les services d'informations utilisateur sous-jacents, la gestion des sessions et des informations d'identification, etc., il s'agit de l'une des principales gammes de produits du groupe, proposant des centaines de produits. de milliards d'appels chaque jour, un QPS maximal de dizaines de millions et une architecture cloud hybride distribuée à l'échelle mondiale, etc.
En tant qu'ingénieur logiciel, vous travaillerez sur nos produits principaux qui fournissent des fonctionnalités critiques pour notre infrastructure commerciale. En fonction de vos intérêts et de votre expérience, vous pourrez travailler dans un ou plusieurs des domaines suivants : mondialisation, expérience utilisateur, sécurité des données, apprentissage automatique. , haute disponibilité du système et bien plus encore.