0

Je suis nouveau au printemps lot et ne pouvait pas comprendre comment faire ..lot de printemps - l'exécution de plusieurs travaux en parallèle

Fondamentalement, j'ai un poller fichier ressort qui passe toutes les N minutes pour rechercher des fichiers avec un nom (ex: A.txt & B.txt) dans certains répertoires. A tout moment, il peut y avoir 2 fichiers maximum dans ce répertoire (A et B). Grâce à Spring Batch Job, ces deux fichiers seront traités et conservés dans deux tables DB différentes.

Ces fichiers sont quelque peu similaires, donc le même processeur/graveur est utilisé.

À l'heure actuelle, comme je l'ai défini, 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), y a-t-il un moyen de créer 2 jobs afin que les deux jobs puissent être exécutés en parallèle?

Répondre

2

Je crois que vous pouvez. Puisque vous êtes nouveau dans le lot de printemps (tout comme moi), je vous recommande de passer par the domain language of a batch 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 (la prise en pension de travail peut être autowired). Cette configuration permettra asynchrone exécution comme visualisé suivant:

Asynchronous

Comparer avec le flux d'exécution synchrone:

enter image description here

Peut-être que cela aiderait en plus de citer le SimpleJobLauncher java doc:

Implant simple mentation de l'interface JobLauncher. L'interface TaskExecutor de Spring Core est utilisée pour lancer un Job. Cela signifie que le type d'exécuteur est très important. Si un SyncTaskExecutor est utilisé, , le travail sera traité dans le même thread qui a appelé le lanceur . Veillez à ce que tous les utilisateurs de cette classe comprennent parfaitement si l'exécution de TaskExecutor démarrera ou non les tâches de manière synchrone ou asynchrone. Le paramètre par défaut utilise un exécuteur de tâche synchrone.

Plus de détails et d'options de configuration - here.

À la fin, il suffit de créer les emplois avec différents noms et/ou de les lancer avec des paramètres différents. exemple Naive 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 d'emploi asynchrone va créer deux instances de travail ce qui exécuteront en parallèle. Ceci est juste une option, qui peut ou peut ne pas convenir à votre contexte.

3

Il existe de très bonnes approches pour exécuter des tâches en mode asynchrone avec Spring, c'est juste une question de comment est configuré le JobLauncher. Le JobLauncher a 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. Par exemple, SimpleAsyncTaskExecutor est un exécuteur de tâches qui va créer un nouveau Thread sur n'importe quel appel et qui pourrait générer un problème de performance si l'exécution s'exécute à haute fréquence. D'un autre côté, il existe également des types TaskExecutors qui fournissent des fonctionnalités de regroupement afin de réutiliser les ressources et de maximiser l'efficacité du système.

Voici un petit exemple de la façon dont configurer un ThreadPoolTaskExecutor:

A) Configurer ThreadPoolTaskExecutor Bean

@Bean 
    public ThreadPoolTaskExecutor taskExecutor() { 
    ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); 
    taskExecutor.setCorePoolSize(15); 
    taskExecutor.setMaxPoolSize(20); 
    taskExecutor.setQueueCapacity(30); 
    return taskExecutor; 
} 

B) Configurer JobLauncher Bean

@Bean 
    public JobLauncher jobLauncher(ThreadPoolTaskExecutor taskExecutor, JobRepository jobRepository){ 
     SimpleJobLauncher jobLauncher = new SimpleJobLauncher(); 
     jobLauncher.setTaskExecutor(taskExecutor); 
     jobLauncher.setJobRepository(jobRepository); 
     return jobLauncher; 
    } 

C) Injecter votre JobLauncher et votre Jobs configuration

@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 {