Je suis nouveau dans le lot de printemps et je ne savais pas comment faire cela ..
Fondamentalement, j'ai un poller de fichier de printemps qui s'exécute toutes les N minutes pour rechercher des fichiers avec un nom (ex: A.txt & B.txt) dans un certain répertoire. À tout moment, il pourrait y avoir au maximum 2 fichiers dans ce répertoire (A et B). Grâce à Spring Batch Job, ces deux fichiers seront traités et conservés dans 2 tables de base de données différentes.
Ces fichiers sont quelque peu similaires, donc le même processeur/graveur est utilisé.
À l'heure actuelle, comme je l'ai configuré, chaque fichier du cycle d'interrogation 1 est récupéré et le travail est exécuté.
Disons qu'il y a 2 fichiers dans le répertoire (A.txt et B.txt), existe-t-il un moyen de créer 2 jobs pour que les deux jobs puissent être exécutés en parallèle?
Je crois que vous le pouvez. Puisque vous êtes nouveau dans le lot de printemps (comme moi), je vous recommande de passer par la langue du domaine d'un lot si vous ne l'avez pas déjà fait.
Ensuite, vous pouvez commencer par configurer votre propre asynchroneJobLauncher
. Par exemple:
@Bean
public JobLauncher jobLauncher() throws Exception
{
SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
jobLauncher.setJobRepository(jobRepository);
jobLauncher.setTaskExecutor(new SimpleAsyncTaskExecutor());
jobLauncher.afterPropertiesSet();
return jobLauncher;
}
Portez une attention particulière à SimpleAsyncTaskExecutor
(le référentiel de tâches peut être câblé automatiquement). Cette configuration permettra asynchrone l'exécution comme visualisé ensuite:
Comparez-le avec le flux d'exécution synchrone:
Il serait peut-être également utile de citer le SimpleJobLauncher
Java doc:
Implémentation simple de l'interface JobLauncher. L'interface Spring Core TaskExecutor est utilisée pour lancer un Job. Cela signifie que le type d'ensemble d'exécuteurs est très important. Si un SyncTaskExecutor est utilisé, le travail sera traité dans le même thread qui a appelé le lanceur. Il convient de veiller à ce que tous les utilisateurs de cette classe comprennent parfaitement si l'implémentation de TaskExecutor utilisée démarrera les tâches de manière synchrone ou asynchrone. Le paramètre par défaut utilise un exécuteur de tâches synchrone.
Plus de détails et d'options de configuration - ici .
À la fin, créez simplement les travaux avec différents noms et/ou lancez-les avec un jeu de paramètres différent. Un exemple naïf serait:
@Autowired
public JobBuilderFactory jobBuilderFactory;
public Job createJobA() {
return jobBuilderFactory.get("A.txt")
.incrementer(new RunIdIncrementer())
.flow(step1())
.next(step2())
.end()
.build();
}
public Job createJobB() {
return jobBuilderFactory.get("B.txt")
.incrementer(new RunIdIncrementer())
.flow(step1())
.next(step2())
.end()
.build();
}
L'exécution de ces travaux avec votre lanceur de travaux asynchrone créera deux instances de travaux qui s'exécuteront en parallèle. Ceci est juste une option, qui peut ou non convenir à votre contexte.
Il existe de très bonnes approches pour exécuter des jobs en mode asynchrone avec Spring, c'est juste une question de configuration de JobLauncher
. JobLauncher
possède une propriété taskExecutor
et l'exécution asynchrone peut être activée en fonction de l'implémentation affectée à cette propriété.
Vous pouvez trouver tous les types TaskExecutor
que Spring peut fournir et en fonction de vos besoins, sélectionnez la meilleure approche pour accomplir vos tâches asynchrones par lots. Types d'exécuteurs de tâches au printemps
Par exemple, SimpleAsyncTaskExecutor
est un exécuteur de tâches qui créera un nouveau Thread
à chaque appel et qui pourrait générer un problème de performances si l'exécution s'exécute à haute fréquence. D'autre part, il existe également des types TaskExecutors
qui fournissent des fonctionnalités de mise en commun afin de réutiliser les ressources et de maximiser l'efficacité du système.
Voici un petit exemple de la façon de configurer un ThreadPoolTaskExecutor
:
A) Configurer le bean ThreadPoolTaskExecutor
@Bean
public ThreadPoolTaskExecutor taskExecutor() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setCorePoolSize(15);
taskExecutor.setMaxPoolSize(20);
taskExecutor.setQueueCapacity(30);
return taskExecutor;
}
B) Configurer le JobLauncher Bean
@Bean
public JobLauncher jobLauncher(ThreadPoolTaskExecutor taskExecutor, JobRepository jobRepository){
SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
jobLauncher.setTaskExecutor(taskExecutor);
jobLauncher.setJobRepository(jobRepository);
return jobLauncher;
}
C) Injectez votre configuration JobLauncher
et Jobs
@Autowired
private JobLauncher jobLauncher;
@Autowired
@Qualifier("job1-file-A")
private Job job1;
@Autowired
@Qualifier("job2-file-B")
private Job job2;
D) Planifier les travaux
@Scheduled(cron = "*/1 * * * * *")
public void run1(){
Map<String, JobParameter> confMap = new HashMap<>();
confMap.put("time", new JobParameter(System.currentTimeMillis()));
JobParameters jobParameters = new JobParameters(confMap);
try {
jobLauncher.run(job1, jobParameters);
}catch (Exception ex){
logger.error(ex.getMessage());
}
}
@Scheduled(cron = "*/1 * * * * *")
public void run2(){
Map<String, JobParameter> confMap = new HashMap<>();
confMap.put("time", new JobParameter(System.currentTimeMillis()));
JobParameters jobParameters = new JobParameters(confMap);
try {
jobLauncher.run(job2, jobParameters);
}catch (Exception ex){
logger.error(ex.getMessage());
}
}
E) Enfin sur votre classe SpringBoot @EnableBatchProcessing
et @EnableScheduling
@EnableBatchProcessing
@EnableScheduling
@SpringBootApplication
public class MyBatchApp {