私はSpringバッチを初めて使用するので、これを行う方法を理解できませんでした。
基本的に私は特定のディレクトリでいくつかの名前(例:A.txt&B.txt)のファイルを探すためにN分ごとに実行するSpringファイルポーラーを持っています。いつでも、このディレクトリ(AおよびB)に最大2つのファイルが存在する可能性があります。 Spring Batch Jobにより、これらの2つのファイルが処理され、2つの異なるDBテーブルに保持されます。
これらのファイルは多少似ているため、同じプロセッサ/ライターが使用されます。
今私が設定した方法では、すべてのポーリングサイクルで1つのファイルが取得され、ジョブが実行されます。
ディレクトリに2つのファイル(A.txtとB.txt)があるとします。2つのジョブを作成して、両方のジョブを並行して実行できるようにする方法はありますか?
できると思います。あなたは春のバッチに新しいので(ちょうど私のように)まだ行っていない場合は、 バッチのドメイン言語 を実行することをお勧めします。
次に、独自のasynchronousJobLauncher
を構成することから始めます。例えば:
@Bean
public JobLauncher jobLauncher() throws Exception
{
SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
jobLauncher.setJobRepository(jobRepository);
jobLauncher.setTaskExecutor(new SimpleAsyncTaskExecutor());
jobLauncher.afterPropertiesSet();
return jobLauncher;
}
SimpleAsyncTaskExecutor
に特に注意してください(ジョブリポジトリは自動接続できます)。この構成では、次に視覚化されるように非同期実行が可能になります。
同期実行フローと比較してください。
SimpleJobLauncher
Java doc:
JobLauncherインターフェースの単純な実装。 Spring Core TaskExecutorインターフェースを使用して、ジョブを起動します。これは、エグゼキューターセットのタイプが非常に重要であることを意味します。 SyncTaskExecutorが使用される場合、ジョブはランチャーを呼び出した同じスレッド内で処理されます。このクラスのすべてのユーザーが、使用されるTaskExecutorの実装が同期または非同期にタスクを開始するかどうかを完全に理解できるように注意する必要があります。デフォルト設定では、同期タスクエグゼキューターが使用されます。
詳細と設定オプション- ここ 。
最後に、differentの名前でジョブを作成するか、異なるパラメーターセットでジョブを起動します。素朴な例は次のようになります:
@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();
}
非同期ジョブランチャーでこれらのジョブを実行すると、2つのジョブインスタンスが作成され、それらが並行して実行されます。これは1つのオプションにすぎず、状況に応じて適切な場合とそうでない場合があります。
Springで非同期モードでジョブを実行するための非常に優れたアプローチがありますが、それはJobLauncher
の構成方法の問題です。 JobLauncher
にはtaskExecutor
プロパティがあり、そのプロパティに割り当てられている実装に応じて非同期実行をアクティブ化できます。
Springが提供できるすべてのTaskExecutor
タイプを見つけることができ、ニーズに応じてバッチ非同期ジョブを実行するための最良のアプローチを選択します。 春のタスク実行者タイプ
たとえば、SimpleAsyncTaskExecutor
は任意の呼び出しで新しいThread
を作成するタスク実行プログラムであり、実行が高頻度で実行されるとパフォーマンスの問題を生成する可能性があります。一方、リソースを再利用してシステムの効率を最大化するためにプール機能を提供するTaskExecutors
タイプもあります。
ThreadPoolTaskExecutor
の構成方法の小さな例を次に示します。
A)ThreadPoolTaskExecutor Beanを構成する
@Bean
public ThreadPoolTaskExecutor taskExecutor() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setCorePoolSize(15);
taskExecutor.setMaxPoolSize(20);
taskExecutor.setQueueCapacity(30);
return taskExecutor;
}
B)JobLauncher Beanを構成する
@Bean
public JobLauncher jobLauncher(ThreadPoolTaskExecutor taskExecutor, JobRepository jobRepository){
SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
jobLauncher.setTaskExecutor(taskExecutor);
jobLauncher.setJobRepository(jobRepository);
return jobLauncher;
}
C)JobLauncher
とJobs
構成を挿入する
@Autowired
private JobLauncher jobLauncher;
@Autowired
@Qualifier("job1-file-A")
private Job job1;
@Autowired
@Qualifier("job2-file-B")
private Job job2;
D)ジョブをスケジュールする
@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)最後にSpringBootクラスで@EnableBatchProcessing
および@EnableScheduling
@EnableBatchProcessing
@EnableScheduling
@SpringBootApplication
public class MyBatchApp {