我正在尝试使用基于注释的方法创建一个Spring批处理应用程序,该方法将由quartz scheduler触发,但会遇到以下问题。
当触发作业时,每个分区按顺序执行而不是并行执行,即如果我有10个分区而不是所有10个分区被一起触发/处理,则逐个处理。
当多个作业实例(根据我的要求需要)被触发时,它没有正确同步,即当第二个实例启动时,它使用第一个实例数据,第一个实例将停止处理但将处于活动状态
以下是我的配置/类文件。
BatchConfiguration.java -
@Configuration
@EnableBatchProcessing
public class BatchConfiguration
{
@Autowired
private JobBuilderFactory jobBuilders;
@Autowired
private StepBuilderFactory stepBuilders;
@Bean
@StepScope
public JdbcCursorItemReader reader(@Value("#{stepExecutionContext[someParam]}") String someParam) {
JdbcCursorItemReader jdbcCursorItemReader = new JdbcCursorItemReader();
jdbcCursorItemReader.setDataSource(getDataSource());
jdbcCursorItemReader.setSql("myQuery");
jdbcCursorItemReader.setRowMapper(new NotifRowMapper());
return jdbcCursorItemReader;}
@Bean
@StepScope
public MyProcessor processor() {
return new MyProcessor();}
@Bean
public MyPartitioner partitioner() {
MyPartitioner partitioner = new MyPartitioner();
partitioner.setDataSource(getDataSource());
partitioner.setSql("MyPartitionerQuery");
return partitioner;}
@Bean
@StepScope
public JdbcBatchItemWriter writer(DataSource dataSource) {
JdbcBatchItemWriter writer = new JdbcBatchItemWriter();
writer.setItemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider());
writer.setSql("MyWriterQuery");
writer.setDataSource(dataSource);
return writer;}
@Bean
public Job springBatch() {
return jobBuilders.get("springBatch").start(masterStep()).build();}
@Bean
public Step masterStep() {
return stepBuilders.get("masterStep")
.partitioner(slave(reader(null), writer(getDataSource()),processor()))
.partitioner("slave", partitioner())
.taskExecutor(taskExecutor()).build();}
@Bean
public Step slave(JdbcCursorItemReader reader,JdbcBatchItemWriter writer, MyProcessor processor) {
return stepBuilders.get("slave")
.chunk(100).reader(reader).processor(processor).writer(writer).build();}
@Bean
public TaskExecutor taskExecutor() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setMaxPoolSize(20);
taskExecutor.afterPropertiesSet();
return taskExecutor;}
@Bean
public JdbcTemplate jdbcTemplate(DataSource dataSource) {
return new JdbcTemplate(dataSource);}
@Bean
public DataSource getDataSource() {
return dataSource;
}
@Bean
public JobRepository getJobRepository() throws Exception {
MapJobRepositoryFactoryBean factory = new MapJobRepositoryFactoryBean();
factory.setTransactionManager(new ResourcelessTransactionManager());
factory.afterPropertiesSet();
factory.setIsolationLevelForCreate("ISOLATION_READ_COMMITTED");
return (JobRepository) factory.getObject();
}}
QuartzJob.java(触发弹簧批处理作业) -
public class QuartzJob implements org.quartz.Job
{
@Override
public void execute(org.quartz.JobExecutionContext jobExecutionContext) throws org.quartz.JobExecutionException
{
AnnotationConfigApplicationContext context;
try
{
context = new AnnotationConfigApplicationContext(BatchConfiguration.class);
JobLauncher jobLauncher = context.getBean(JobLauncher.class);
org.springframework.batch.core.Job newJob = context.getBean("springBatch", org.springframework.batch.core.Job.class);
JobParameters param = new JobParametersBuilder().addLong("time",System.currentTimeMillis()).toJobParameters();
jobLauncher.run(newJob, param);
} catch (Exception e){}}}
MyQuartzListener.java(类在服务器启动期间触发quartz作业) -
public class MyQuartzListener implements ServletContextListener
{
private Scheduler scheduler;
@Override
public void contextDestroyed(ServletContextEvent arg0){ }
@Override
public void contextInitialized(ServletContextEvent ctx)
{
JobDetail job = JobBuilder.newJob(QuartzJob.class).withIdentity("SPRINGBATCH", "SPRINGBATCH").build();
Trigger trigger = TriggerBuilder.newTrigger().withIdentity("SPRINGBATCH", "SPRINGBATCH").startNow().withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(60).repeatForever()).build();
try
{
scheduler = ((StdSchedulerFactory) ctx.getServletContext().getAttribute(QuartzInitializerListener.QUARTZ_FACTORY_KEY)).getScheduler();
job.getJobDataMap().put("quartztime", System.currentTimeMillis());
scheduler.scheduleJob(job, trigger);
} catch (SchedulerException e) {} }
}
MyPartitioner .java
public class MyPartitioner implements Partitioner
{
@Override
public Map<String, ExecutionContext> partition(int gridSize)
{
Map<String, ExecutionContext> partitionMap = new HashMap<String, ExecutionContext>();
List<String> partitionCodes = getPartitionCodes(sql);
int count = 1;
for (String partitionCode : partitionCodes)
{
ExecutionContext context = new ExecutionContext();
context.put("partitionCode", partitionCode);
context.put("name", "Thread" + count);
partitionMap.put(partitionCode, context);
count++;
}
return partitionMap;}}
此配置有问题吗?我将当前时间传递给每个工作实例以单独识别每个实例,但仍然无法正常工作。