Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-mvc/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Spring batch 使用spring批处理处理大型文件_Spring Batch - Fatal编程技术网

Spring batch 使用spring批处理处理大型文件

Spring batch 使用spring批处理处理大型文件,spring-batch,Spring Batch,我有一个大文件,可能包含100K到500K的记录。我计划使用面向块的处理,我的想法是 1) 根据每个文件中的计数(比如10K),将大文件拆分为小文件 2) 如果有10万条记录,那么我将得到10个文件,每个文件包含10万条REOCRD 3) 我想分区这10个文件,并希望使用5个线程处理。我正在考虑使用customMultiResourcePartioner 4) 这5个线程应该处理split进程中创建的所有10个文件 5) 我不想创建与文件计数相同数量的线程,因为在这种情况下,我可能会面临内存问题

我有一个大文件,可能包含100K到500K的记录。我计划使用面向块的处理,我的想法是

1) 根据每个文件中的计数(比如10K),将大文件拆分为小文件

2) 如果有10万条记录,那么我将得到10个文件,每个文件包含10万条REOCRD

3) 我想分区这10个文件,并希望使用5个线程处理。我正在考虑使用customMultiResourcePartioner

4) 这5个线程应该处理split进程中创建的所有10个文件

5) 我不想创建与文件计数相同数量的线程,因为在这种情况下,我可能会面临内存问题。我想看的是,无论我想用5个线程处理多少个文件(我可以根据需要增加)

专家您能告诉我这可以通过使用spring batch实现吗?如果是,请共享指针或参考实现

提前谢谢

工作作业配置xml

<description>Spring Batch File Chunk Processing</description>

<import resource="../config/batch-context.xml" />

<batch:job id="file-partition-batch" job-repository="jobRepository" restartable="false">        
    <batch:step id="master">
        <batch:partition partitioner="partitioner" handler="partitionHandler" />
    </batch:step>
</batch:job>

<batch:step id="slave">
    <batch:tasklet>
        <batch:chunk reader="reader" processor="compositeProcessor"
            writer="compositeWriter" commit-interval="5">
        </batch:chunk>
    </batch:tasklet>
</batch:step>

<bean id="partitionHandler" class="org.springframework.batch.core.partition.support.TaskExecutorPartitionHandler">
    <property name="taskExecutor" ref="taskExecutor"/>
    <property name="step" ref="slave" />
    <property name="gridSize" value="5" />
</bean>

<bean id="partitioner" class="com.poc.partitioner.FileMultiResourcePartitioner">
    <property name="resources" value="file:/Users/anupghosh/Documents/Spring_Batch/FilePartitionBatch/*.txt" />
    <property name="threadName" value="feed-processor" />
</bean>

<bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
    <property name="corePoolSize" value="5" />
    <property name="maxPoolSize" value="5" />
</bean>

<bean id="reader" class="org.springframework.batch.item.file.FlatFileItemReader" scope="step">
    <property name="resource" value="#{stepExecutionContext['fileName']}" />

    <property name="lineMapper">
        <bean class="org.springframework.batch.item.file.mapping.DefaultLineMapper">
        <property name="lineTokenizer">
            <bean class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
                <property name="delimiter" value="|"/>
                <property name="names" value="key,docName,docTypCD,itemType,itemNum,launchDate,status" />
            </bean>
        </property>
        <property name="fieldSetMapper">
            <bean class="com.poc.mapper.FileRowMapper" />
        </property>
        </bean>
    </property>
</bean>

<bean id="validatingProcessor" class="org.springframework.batch.item.validator.ValidatingItemProcessor">
    <constructor-arg ref="feedRowValidator" />
</bean>

<bean id="feedProcesor" class="com.poc.processor.FeedProcessor" />

<bean id="compositeProcessor" class="org.springframework.batch.item.support.CompositeItemProcessor" scope="step">
    <property name="delegates">
        <list>
            <ref bean="validatingProcessor" />
            <ref bean="feedProcesor" />
        </list>
    </property>
</bean>

<bean id="recordDecWriter" class="com.poc.writer.RecordDecWriter" />

<bean id="reconFlatFileCustomWriter" class="com.poc.writer.ReconFileWriter">
    <property name="reconFlatFileWriter" ref="reconFlatFileWriter" />
</bean>

<bean id="reconFlatFileWriter" class="org.springframework.batch.item.file.FlatFileItemWriter" scope="step">
    <property name="resource" value="file:/Users/anupghosh/Documents/Spring_Batch/recon-#{stepExecutionContext[threadName]}.txt" />
    <property name="shouldDeleteIfExists" value="true" />
    <property name="lineAggregator">
        <bean class="org.springframework.batch.item.file.transform.DelimitedLineAggregator">
            <property name="delimiter" value="|" />
            <property name="fieldExtractor">
                <bean class="org.springframework.batch.item.file.transform.BeanWrapperFieldExtractor">
                    <property name="names" value="validationError" />
                </bean>
            </property>
        </bean>
    </property>
</bean>

<bean id="compositeWriter" class="org.springframework.batch.item.support.CompositeItemWriter">
    <property name="delegates">
        <list>
            <ref bean="recordDecWriter" />
            <ref bean="reconFlatFileCustomWriter" />
        </list>
    </property>
</bean>

<bean id="feedRowValidator" class="org.springframework.batch.item.validator.SpringValidator">
    <property name="validator">
        <bean class="com.poc.validator.FeedRowValidator"/>
    </property>
</bean>     
Spring批处理文件块处理

能够使用MultiResourcePartitioner解决这个问题。下面是java配置

@Bean
    public Partitioner partitioner() {
        MultiResourcePartitioner partitioner = new MultiResourcePartitioner();
        ClassLoader cl = this.getClass().getClassLoader();
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(cl);
        Resource[] resources = resolver.getResources("file:" + filePath + "/"+"*.csv");     
        partitioner.setResources(resources);
        partitioner.partition(10);      
        return partitioner;
    }

    @Bean
    public TaskExecutor taskExecutor() {
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        taskExecutor.setMaxPoolSize(4);
        taskExecutor.afterPropertiesSet();
        return taskExecutor;
    }   

    @Bean
    @Qualifier("masterStep")
    public Step masterStep() {
        return stepBuilderFactory.get("masterStep")
                .partitioner(ProcessDataStep())
                .partitioner("ProcessDataStep",partitioner())   
                .taskExecutor(taskExecutor())
                .listener(pcStressStepListener)
                .build();
    }


    @Bean
    @Qualifier("processData")
    public Step processData() {
        return stepBuilderFactory.get("processData")
                .<pojo, pojo> chunk(5000)
                .reader(reader)             
                .processor(processor())
                .writer(writer)         
                .build();
    }



    @Bean(name="reader")
    @StepScope
    public FlatFileItemReader<pojo> reader(@Value("#{stepExecutionContext['fileName']}") String filename) {

        FlatFileItemReader<pojo> reader = new FlatFileItemReader<>();
        reader.setResource(new UrlResource(filename));
        reader.setLineMapper(new DefaultLineMapper<pojo>() {
            {
                setLineTokenizer(new DelimitedLineTokenizer() {
                    {
                        setNames(FILE HEADER);


                    }
                });
                setFieldSetMapper(new BeanWrapperFieldSetMapper<pojo>() {
                    {
                        setTargetType(pojo.class);
                    }
                });
            }
        });
        return reader;
    }   
@Bean
公共分区器分区器(){
MultiResourcePartitioner partitioner=新的MultiResourcePartitioner();
ClassLoader cl=this.getClass().getClassLoader();
ResourcePatternResolver解析器=新路径匹配ResourcePatternResolver(cl);
Resource[]resources=resolver.getResources(“文件:“+filePath+”/“+”*.csv”);
partitioner.setResources(资源);
分区器。分区(10);
返回分区器;
}
@豆子
公共任务执行器任务执行器(){
ThreadPoolTaskExecutor taskExecutor=新的ThreadPoolTaskExecutor();
taskExecutor.setMaxPoolSize(4);
taskExecutor.AfterPropertieSet();
返回任务执行器;
}   
@豆子
@限定词(“主步骤”)
公共步骤masterStep(){
return stepBuilderFactory.get(“masterStep”)
.partitioner(ProcessDataStep())
.partitioner(“ProcessDataStep”,partitioner())
.taskExecutor(taskExecutor())
.listener(PCStepListener)
.build();
}
@豆子
@限定符(“processData”)
公共步骤processData(){
返回stepBuilderFactory.get(“processData”)
.chunk(5000)
.读卡器(读卡器)
.processor(处理器())
.作者(作者)
.build();
}
@Bean(name=“reader”)
@步进镜
公共FlatFileItemReader读取器(@Value(“#{stepExecutionContext['fileName']}”)字符串文件名){
FlatFileItemReader=新的FlatFileItemReader();
setResource(新的UrlResource(文件名));
reader.setLineMapper(新的DefaultLineMapper(){
{
setLineTokenizer(新的DelimitedLineTokenizer(){
{
设置名称(文件头);
}
});
setFieldSetMapper(新的BeanRapperFieldSetMapper(){
{
setTargetType(pojo.class);
}
});
}
});
返回读取器;
}   

您确实正确地安排了流程。您的具体问题是什么?感谢@MichaelMinella在短时间内做出回应。我的问题是:如果在分割处理后我有10个文件(可能更多),我将如何使用5个线程处理这些文件?更具体地说,我将如何对这些文件进行分区,以便5个线程将处理所有这10个文件。
MultiResourcePartitioner
是创建分区的正确方法。从那里,使用
TaskExecutionPartitionHandler
,您可以通过
TaskExecutor
的配置来控制使用了多少线程。默认情况下,它使用
SyncTaskExecutor
,但我们希望您配置其他类似
ThreadPoolTaskExecutor
。在该
TaskExecutor
中,您可以配置最大线程数等。非常感谢@MichaelMinella遵照您的建议,我终于让它工作了。我感谢你的帮助。我已经编辑了我的答案,并添加了我的作业配置xml的工作版本,因为注释中存在大小限制。也许这对某人有用。请让我知道如何接受“答案”@Anup您是如何分割文件的?还需要添加taskExecutor.setCorePoolSize(4)和taskExecutor.setQueueCapacity(8)以使多线程工作。