Spring Batch並行與擴展


1. 概述

Spring Batch提供了多種方式用於處理並行,提高性能。主要分為2大類: 
- 單個進程,多線程 
- 多個進程

因此,可以細分為以下幾類: 
- 多線程Step(Multi-thread Step,single process) 
- 並行Step(Parallel Steps, single process ) 
- Remote Chunking of Step( multi process) 
- Partitioning a step(single or multi process)

2. Multi-Thread Step

最直接的方式是給Step配置一個TaskExecutor

<step id="loading">
    <tasklet task-executor="taskExecutor">...</tasklet>
</step>

 

此時,taskExecutor的線程並行來執行Item處理(統一item的read,process,write在同一個線程中執行)。可以限制TaskExecutor的閾值(默認為4):

<step id="loading"> <tasklet
    task-executor="taskExecutor"
    throttle-limit="20">...</tasklet>
</step>

 

需要注意的是,在多線程Step中,需要確保Reader、Processor和Writer是線程安全的,否則容易出現並發問題。Spring Batch提供的大部分組件都是非線程安全的,他們都保存有部分狀態信息,主要是為了支持任務重啟。

因此,使用多線程Step的核心任務是實現無狀態化,例如不保存當前讀取的item的cursor,而是同item的flag字段來區分item是否被處理過,已經被處理過的下次重啟的時候,直接被過濾掉。

多線程Step實現的是單個Step的多線程化。

3. Parallel Steps

如果多個Step沒有先后關系,可以並行執行,這是通過split和flow來實現的:

<job id="job1">
    <split id="split1" task-executor="taskExecutor" next="step4">
        <flow>
            <step id="step1" parent="s1" next="step2"/>
            <step id="step2" parent="s2"/>
        </flow>
        <flow>
            <step id="step3" parent="s3"/>
        </flow>
    </split>
    <step id="step4" parent="s4"/>
</job>

<beans:bean id="taskExecutor" class="org.spr...SimpleAsyncTaskExecutor"/>

 

該種模式提供的是多個Step的並行處理。

4. Remote Chunking

Remote chunking 的示意圖如下: 
這里寫圖片描述

Master為單個進程,因此只有在處理所需要的時間遠遠大於讀取所需要的時間的時候,這個方式才適用,否則Master容易成為瓶頸。

Master是一個常規的Step實現,只不過它的ItemWriter知道如何將Items分塊,並發送到中間件(例如JMS),通過實現ChunkProvider接口來實現。

public interface ChunkProvider<T>{
    Chunk<T> provide(StepContribution contribution) throws Exception;
    void postProcess(StepContribution contribution, Chunk<T> chunk);
}

 

Slave則充當中間件的Listener,通過ItemProcessor和ItemWriter來實現item處理,具體的是通過實現ChunkProcessor接口

public interface ChunkProcessr<T> {
    void process(StepContribution contribution,Chunk<T> chunk) throws Exception;
}

 

可以看到,remote chunking實現的是(Processor、Writer)的並行化。分區不需要對數據源的結構有很明確的了解。

5. Partitioning

Step分區處理示意圖如下: 
這里寫圖片描述

一個分區配置如下:

<step id="step1.master">
    <partition step="step1" partitioner="partitioner">
        <handler grid-size="10" task-executor="taskExecutor"/>
    </partition>
</step>

<step id="step1">
    <tasklet>
        <chunk reader="" writer"" processor="" .../>
    </tasklet>
</step>

 

主要包括2個步驟: 
1. 數據分區 
2. 分區處理

具體的分區執行流程如下: 
這里寫圖片描述

PartitionHandler

其中PartitionHandler知道集群環境,根據下面要介紹的Splitter進行分區,發送執行請求(通過WebService ,RMI等方式) 並收集執行結果,聚合,最終反饋給Job。Spring Batch提供了一個同一台機器上的Handler實現,在同一機器上創建多個Step Execution。

<step id="step1.master">
    <partition step="step1" handler="handler"/>
</step>

<bean class="org.spr...TaskExecutorPartitionHandler">
    <property name="taskExecutor" ref="taskExecutor"/>
    <property name="step" ref="step1" />
    <property name="gridSize" value="10" />
</bean>

 

Partitioner

Partitioner負責生成執行上下文,作為Step Execution的輸入參數,其接口定義如下:

public interface Partitioner {
    Map<String, ExecutionContext> partition(int gridSize);
}

 

返回結果中Map的key,是一個唯一的名字,常見的實現方式是step_name + counter。或者通過PartitioneNameProvider來提供。 名字關聯到對應的執行上下文。ExecutionContext只是一個key/value容器,因此它可能包含主鍵范圍,行數等信息。

StepExecutionSplitter

Partitioner生成的ExecutionContext,經過StepExecutionSplitter處理之后形成StepExecution,然后交給Handler處理。StepExecutionSplitter接口定義如下:

public interface StepExecutionSplitter {
    String getStepName();
    Set<StepExecution> split(StepExecution stepExecution , int gridSize) 
                throws JobExecutionException;
}

 

通常,Slave中的Step配置都是相同的,他們通過獲取Partitioner划分好的ExecutionContext,獲取Step的輸入參數,動態綁定到Step中。例如划分的情況如下表:

step execution name(key) ExecutionContext(value)
filecopy:partition0 file_name=/home/data/0
filecopy:partition1 file_name=/home/data/1
filecopy:partition2 file_name=/home/data/2

然后該文件名被綁定到Step的組件中:

<bean id="itemReader" scope="step"
      class="org.spr...MultiResourceItemReader">
    <property name="resource" value="#{stepExecutionContext[file_name]}/*"/>
</bean>

 

整個具體流程如下: 
這里寫圖片描述 
可以看出,Patitioning提供的是(Reader、Processor、Writer)的並行化。分區模式需要對數據源的結構有一定的了解,比如知道主鍵范圍。

 

本文轉自:https://blog.csdn.net/bingduanlbd/article/details/50989664


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM