springBatch

 

Spring Batch 结合 定时调度框架Quartz
https://www.cnblogs.com/larrydpk/p/13660537.html
https://blog.csdn.net/u012921921/article/details/105591216/ 多线程处理

Job Instance:作业实例
Job Parameter:作业参数
Job Execution:作业执行器
https://blog.csdn.net/a18792721831/article/details/109550018


spring.batch.job.enabled=false
spring.batch.initialize-schema=always

spring.datasource.url=jdbc:mysql://127.0.0.1/xmh
spring.datasource.username=root
spring.datasource.password=admin
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
 
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-batch</artifactId>
            <version>2.3.0.RELEASE</version>
        </dependency>
 
@SpringBootApplication
@EnableBatchProcessing

SimpleBatchConfiguration

  

官方: http://www.springsource.org/spring-batch
springBatch待处理:
数据分块,并发处理 远程分块
事物机制
REFERENCES command denied to user 'pahapp'@'10.131.39.87' for table 'batch_job_instance'

spring batch官方文档:https://docs.spring.io/spring-batch
spring batch3.x中文文档:http://www.kailing.pub/SpringBatchReference
spring batch官方入门实例:https://projects.spring.io/spring-batch/
https://www.bbsmax.com/A/8Bz88QV6zx/
手动启动一个job 传入参数
停止一个job
事物 https://blog.csdn.net/neweastsun/article/details/88866837

概念:
JobParameters 一次任务job执行,任务链上的参数
Tasklet 任务的一种实现方式,其他还有Chunks实现

任务场景1:
Chunks实现,一个job任务里,读、处理、写分开共同组成一个step
任务场景2:
Tasklet实现,一个job任务里,由多个step按先后顺序组成

优点:
1,接口、任务job、step管理
2,并行的step处理
3,批处理的精细化管理,元数据存放在数据库中,可以随时监控批处理Job的执行状态
4,可重启性
Job执行期间如果因为异常导致失败,应该能够在失败的点重新启动Job;而不是从头开始重新执行Job。

要点:
1,同一个参数只能启动一次任务 A job instance already exists and is complete for parameters={myParamter=myParamter1111111111111}
jobLauncher.run(MyJob(), parameters);//启动任务
2,面向“块”的step中chunk(2) 一次读取、处理、写入的条数
spring.batch.job.enabled=false来禁止Spring容器自动启动Job
面向“块”的step,有ItemReader, ItemProcessor, 和 ItemWriter 这3个接口
读完以后返回null,job就会自动停下来了
3,多线程step,并行step https://www.cnblogs.com/larrydpk/p/13664256.html

https://www.cnblogs.com/rookiemzl/p/9788002.html

Job Instance(作业实例)是一个运行期的概念,Job每执行一次都会涉及到一个Job Instance。

Job Instance来源可能有两种:一种是根据设置的Job Parameters从Job Repository(作业仓库)中获取一个;如果根据Job Parameters从Job Repository没有获取Job Instance,则新创建一个新的Job Instance。

Job Execution表示Job执行的句柄,一次Job的执行可能成功也可能失败。只有Job执行成功后,对应的Job Instance才会被完成。因此在Job执行失败的情况下,会有一个Job Instance对应多个Job Execution的场景发生。

这里就能明显看到之前设置的chunk的作用了。Writer每次是处理5条记录,如果一条输出一次,会对IO造成压力。

Job Repository来存储Job执行期的元数据(这里的元数据是指Job Instance、Job Execution、Job Parameters、Step Execution、Execution Context等数据),并提供两种默认实现。
一种是存放在内存中;另一种将元数据存放在数据库中。通过将元数据存放在数据库中,可以随时监控批处理Job的执行状态。Job执行结果是成功还是失败,并且使得在Job失败的情况下重新启动Job成为可能。Step表示作业中的一个完整步骤,一个Job可以有一个或者多个Step组成。

框架在Job层面,同样提供了作业编排的概念,包括顺序、条件、并行作业编排。
Chunk支持事务管理,通过commit-interval设置每次提交的记录数;Step的每一次提交作为一个完整的事务存在

Remote Chunking
远程Step技术本质上是将对Item读、写的处理逻辑进行分离;通常情况下读的逻辑放在一个节点进行操作,将写操作分发到另外的节点执行。

分区处理
通过数据分区后,不同的数据已经被分配到不同的作业步执行器中

@Configuration
@EnableBatchProcessing
public class JobDemo implements StepExecutionListener{
    @Autowired
    private JobBuilderFactory jobBuilderFactory;
    @Autowired
    private StepBuilderFactory stepBuilderFactory;
    @Autowired
    private JobLauncher jobLauncher;
    @Autowired
    private JobOperator jobOperator;
    @Autowired
    private JobRepository jobRepository;
    @Autowired
    private JobRegistry jobRegistry;
    @Autowired
    private JobExplorer jobExplorer;
    @Autowired
    private ApplicationContext context;//或者implements ApplicationContextAware 通过构造注入
    //创建一个成员变量
    private Map<String,JobParameter> parameters;

//            .start(readLines())
//            .next(processLines())
//            .next(writeLines())
    @Bean("demo")
    public Job jobDemo() {
        return jobBuilderFactory.get("demo").start(step1()).on("COMPLETED")
                .to(step2()).from(step2()).on("COMPLETED")
                .to(step3()).from(step3()).end()
                .build();
    }
    public Step step3() {
        return stepBuilderFactory.get("step3").tasklet(new Tasklet() {
            @Override
            public RepeatStatus execute(StepContribution stepContribution, ChunkContext chunkContext) throws Exception {
                System.out.println("================step3==============:");
                return RepeatStatus.FINISHED;
            }
        }).build();
    }
    public Step step2() {
        return stepBuilderFactory.get("step2").tasklet(new Tasklet() {
            @Override
            public RepeatStatus execute(StepContribution stepContribution, ChunkContext chunkContext) throws Exception {
                System.out.println("================step2==============");
                return RepeatStatus.FINISHED;
            }
        }).build();
    }
    public Step step1() {
        return stepBuilderFactory.get("step1").listener(this).tasklet(new Tasklet() {
            @Override
            public RepeatStatus execute(StepContribution stepContribution, ChunkContext chunkContext) throws Exception {
                System.out.println("================step1==============:"+parameters.get("myParamter").getValue());
                return RepeatStatus.FINISHED;
            }
        }).build();
    }

    public void lunch(String paramter) throws Exception {
        JobParameters parameters = new JobParametersBuilder()
                .addString("myParamter", paramter)//添加参数
                .toJobParameters();
        jobLauncher.run(jobDemo(), parameters);//启动任务
// jobOperator.start("jobDemo", "meg=" + "");//jobOperator需要自己定义
//自定义的jobOperator需要自己定义
/*SimpleJobOperator jobOperator = new SimpleJobOperator();
jobOperator.setJobLauncher(jobLauncher);
jobOperator.setJobParametersConverter(new DefaultJobParametersConverter());//参数转换器
jobOperator.setJobRepository(jobRepository);//jobRepository持久化
jobOperator.setJobExplorer(jobExplorer);//jobExplorer获取和任务相关的信息
jobOperator.setJobRegistry(jobRegistry);//注册,需要创建,根据job名称获取job对象
*/

    }
    // @Bean
// public JobRegistryBeanPostProcessor registryBeanPostProcessor() throws Exception {
// JobRegistryBeanPostProcessor registryBeanPostProcessor = new JobRegistryBeanPostProcessor();
// registryBeanPostProcessor.setJobRegistry(jobRegistry);
// registryBeanPostProcessor.setBeanFactory(context.getAutowireCapableBeanFactory());
// registryBeanPostProcessor.afterPropertiesSet();
// return registryBeanPostProcessor;
// }
    @Override
    public void beforeStep(StepExecution stepExecution) {
        this.parameters = stepExecution.getJobParameters().getParameters();
    }
    @Override
    public ExitStatus afterStep(StepExecution stepExecution) {
        return null;
    }
}

测试入口
jobDemo.lunch("myParamter1111111111111");

  

@Configuration
@EnableBatchProcessing
public class BatchConfiguration extends DefaultBatchConfigurer {
    @Autowired
    public StepBuilderFactory stepBuilderFactory;
    @Autowired
    public JobBuilderFactory jobBuilderFactory;
    @Autowired
    private JobLauncher jobLauncher;

    @Bean
    public MyItemProcessor processor(){
        return new MyItemProcessor();
    }
    @Bean
    public ItemWriter<String> writer(){
        return new MyItemWriter();
    }
    // @Bean
// public ItemReader<String> textReader(){
// FlatFileItemReader<String> reader=new FlatFileItemReader<>();
// File file = new File("D:\\FTP\\ttest.txt");
// reader.setResource(new FileSystemResource(file));
// reader.setLineMapper(new LineMapper<String>() {
// @Override
// public String mapLine(String line, int lineNumber) throws Exception {
// return line;
// }
// });
// return reader;
// }
    @Bean
    @StepScope
    public ItemReader<String> stringReader(@Value("#{jobParameters[myParamter]}") String param){
        return new MyItemReader(param);
    }
    @Override
    public void setDataSource(DataSource dataSource) {
        super.setDataSource(dataSource);
    }
    @Bean
    public Step myStep(){
        return stepBuilderFactory
                .get("step1")
//这个chunk size是最后调用写入的时候,一次性写入多少条已处理的数据
                .<String,String>chunk(2)
// .reader(textReader())
                .reader(stringReader(""))
                .processor(processor())
                .writer(writer())
                .listener(new ItemWriteListener<String>(){
                    @Override
                    public void beforeWrite(List<? extends String> list) {
                        System.out.println("beforeWrite:"+list);
                    }
                    @Override
                    public void afterWrite(List<? extends String> list) {
                        System.out.println("afterWrite:"+list);
                    }
                    @Override
                    public void onWriteError(Exception e, List<? extends String> list) {
                    }
                })
                .build();
    }

    @Bean
    public Job MyJob(){
        return jobBuilderFactory
                .get("MyJOB")
                .listener(new JobExecutionListenerSupport(){
                    @Override
                    public void beforeJob(JobExecution jobExecution) {
                        System.out.println("beforeJob执行执行做处理");
                    }
                    //所有处理结束后调用
                    @Override
                    public void afterJob(JobExecution jobExecution) {
                        System.out.println("afterJob执行执行做处理");
                        if(jobExecution.getStatus() == BatchStatus.COMPLETED){
                            System.out.println("JobExecutionListenerSupport*****OK");
                        }
                    }
                })
                .flow(myStep())
                .end()
                .build();
    }

    //同一个参数只能启动一次任务 A job instance already exists and is complete for parameters={myParamter=myParamter1111111111111}
    public void lunch(String paramter) throws Exception {
        JobParameters parameters = new JobParametersBuilder()
                .addString("myParamter", paramter)//添加参数
                .toJobParameters();
        jobLauncher.run(MyJob(), parameters);//启动任务
    }
}

public class MyItemReader implements ItemReader<String> {
    private int i;
    private String param;
    public MyItemReader(String param) {
        this.param = param;
    }
    @Override
    public String read() throws Exception{
        System.out.println("MyItemReader:"+param);
        if(i >= 3){
            return null;
        }
        i++;
        return param;
    }
}

public class MyItemProcessor implements ItemProcessor<String,String> {
    public Object processItem(Object o) throws Exception {
        return null;
    }
    @Override
    public String process(String s) throws Exception {
        System.out.println("MyItemProcessor:"+s);
        return s+"---------PROCESSED";
    }
}

public class MyItemWriter implements ItemWriter<String> {
    @Override
    public void write(List<? extends String> items) throws Exception {
        for (String item : items) {
            System.out.println("MyItemWriter:"+item);
        }
    }
}

  

    元数据存储到数据库
    @Bean
    public DataSource dataSourceMy(){
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://10.20.25.138:3307/db_pajkx_sportaward?zeroDateTimeBehavior=convertToNull");
        dataSource.setPassword("123456");
        dataSource.setUsername("pahapp");
        return dataSource;
    }
    @Bean
    public ResourcelessTransactionManager transactionManager() {
        return new ResourcelessTransactionManager();
    }
    @Bean
    public JobRepository jobRepository(ResourcelessTransactionManager transactionManager) throws Exception {
        System.out.println("***************************jobRepository:datasource:"+dataSourceMy()+",this.getTransactionManager():"+this.getTransactionManager()
                +",transactionManager:"+transactionManager);
        JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
        factory.setDataSource(dataSourceMy());
        factory.setTransactionManager(transactionManager);
// factory.setIsolationLevelForCreate("ISOLATION_SERIALIZABLE");//ISOLATION_SERIALIZABLE SERIALIZABLE
        factory.setTablePrefix("BATCH_");
        factory.setMaxVarCharLength(1000);
        return factory.getObject();
    }
    @Bean
    public SimpleJobLauncher jobLauncher(JobRepository jobRepository) {
        SimpleJobLauncher simpleJobLauncher = new SimpleJobLauncher();
        simpleJobLauncher.setJobRepository(jobRepository);
        return simpleJobLauncher;
    }

    @Autowired
    JobLauncher jobLauncher;
    @Autowired
    @Qualifier("myJob")
    Job myJob;
    JobParameters parameters = new JobParametersBuilder()
            .addString("myParamter", request.getUserId())//添加参数
            .toJobParameters();
    jobLauncher.run(myJob, parameters);//启动任务



    元数据存储到内存
    @Bean
    public ResourcelessTransactionManager transactionManager() {
        return new ResourcelessTransactionManager();
    }
    @Bean
    public JobRepository jobRepository(ResourcelessTransactionManager transactionManager) throws Exception {
        MapJobRepositoryFactoryBean mapJobRepositoryFactoryBean = new MapJobRepositoryFactoryBean(transactionManager);
        mapJobRepositoryFactoryBean.setTransactionManager(transactionManager);
        return mapJobRepositoryFactoryBean.getObject();
    }
    @Bean
    public SimpleJobLauncher jobLauncher(JobRepository jobRepository) {
        SimpleJobLauncher simpleJobLauncher = new SimpleJobLauncher();
        simpleJobLauncher.setJobRepository(jobRepository);
        return simpleJobLauncher;
    }

  

 

posted @ 2021-07-10 17:53  XUMT111  阅读(605)  评论(0)    收藏  举报