spring batch 学习笔记

1.spring batch 轻量级的,完全面向spring的批处理框架,可以应用于企业级大量的数据处理系统。

2.数据量大、系统根据配置自动完成,无需人工干预、定期执行。

3.应用可以拆分为3个环节:读数据、数据处理、写数据

4.spring batch是一款批处理框架,需要结合调度框架使用。

5.spring-batch-core:批处理领域相关类;spring-batch-infrastructure:基础访问处理框架。

6.所有读操作均需要实现ItemReader接口,支持基于数据库游标和分页两类操作;

7.所有写操作均需要实现ItemWriter接口,该接口只有一个write方法,参数时处理的结果列表。

8.业务处理均需要显示ItemProcesser接口,用于完成相应业务处理。

9.spring batch将批处理任务称为一个job,job下分为多个step;step是一个独立的顺序处理步骤;多个批处理step按照一定的流程组成一个job。

10.step的配置包含:读数据、处理数据、写数据相关的bean,还需要指定commit-interval:事务提交粒度,表名多少条处理完成后,提交一次事务;还需要指定chunk-completion-policy:完成策略,即当发生什么情况时表明该step已经完成,可以转入后续处理,默认策略是读入数据为空时认为step结束。

11.step配置范例:

<job id="messageJob">
  <step id="messageStep">
	<tasklet>
	   <chunk reader="messageReader" processor="messageProcessor" 
	       writer="messageWriter" commit-interval="5" 
	       chunk-completion-policy="">
		</chunk>
	</tasklet>
   </step>
</job>

12.JobRepository用于对job进行管理,并需要为其指定一个事务管理器。

<beans:bean id="jobRepository"
class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean">
		<beans:property name="transactionManager" ref="transactionManager" />
</beans:bean>
<beans:bean id="transactionManager"
class="org.springframework.batch.support.transaction.ResourcelessTransactionManager"/>

13.spring batch提供了JobLauncher接口用于运行Job,我们需要为JobLauncher指定一个JobRepository,指定一个任务执行器,最后通过run方法来执行job,该方法需要指定执行的job参数以及执行参数:JobParameters。

 public class Main {
	public static void main(String[] args) {
            ClassPathXmlApplicationContext c = 
                 new ClassPathXmlApplicationContext("message_job.xml");
            SimpleJobLauncher launcher = new SimpleJobLauncher();
            launcher.setJobRepository((JobRepository) c.getBean("jobRepository"));
            launcher.setTaskExecutor(new SimpleAsyncTaskExecutor());
            try {
                 launcher.run((Job) c.getBean("messageJob"), new JobParameters());
            } catch (Exception e) {
                e.printStackTrace();
            }
	}
}

14.对于srping batch来说,JobParameters相同的任务只能成功运行一次。

Map<String,JobParameter> parameters = new HashMap<String,JobParameter>();
parameters.put(RUN_MONTH_KEY,new JobParameter("2011-10"));
launcher.run((Job) c.getBean("messageJob"),new JobParameters(parameters));
parameters.put(RUN_MONTH_KEY,new JobParameter("2011-11"));
launcher.run((Job) c.getBean("messageJob"),new JobParameters(parameters));

15.spring batch中可以通过配置实现步骤step的重试:

 <job id="messageJob" restartable="true">
	<step id="messageStep">
		<tasklet>
			<chunk reader="messageReader" processor="messageProcessor" writer="messageWriter"
                        commit-interval="5" chunk-completion-policy="" retry-limit="2">
				<retryable-exception-classes>
					<include class="java.lang.RuntimeException" />
				</retryable-exception-classes>
			</chunk>
		</tasklet>
	</step>
</job>

其中:retry-limit为重试次数;retryable-exception-classes为捕获到对应的异常进行重试,也可以配置exclude。

16.任务重试:

spring batch从出错的事务边界内第一条记录重复执行,这样确保了事务的完整性

 Map<String,JobParameter> parameters = new HashMap<String,JobParameter>(); 
 parameters.put(RUN_MONTH_KEY,new JobParameter("2011-10")); 
 launcher.run((Job) c.getBean("messageJob"),new JobParameters(parameters)); 
 Thread.sleep(10000); 
 launcher.run((Job) c.getBean("messageJob"),new JobParameters(parameters));

17.运行时管理:

JobInstance 该类记录了 Job 的运行实例。举例:10 月和 11 月分别执行同一 Job,将生成两个 JobInstance。主要信息有:标识、版本、Job 名称、Job 参数
JobExecution 该类记录了 Job 的运行记录。如上面的示例,Job 第一次运行失败,第二次运行成功,那么将形成两条运行记录,但是对应的是同一个运行实例。主要信息有:Job 的运行时间、运行状态等。
JobParameters 该类记录了 Job 的运行参数
ExecutionContext 该类主要用于开发人员存储任务运行过程中的相关信息(以键值对形式),主要分为 Job 和 Step 两个范围
StepExecution 该类与 JobExecution 类似,主要记录了 Step 的运行记录。包括此次运行读取记录条数、输出记录条数、提交次数、回滚次数、读跳过条数、处理跳过条数、写跳过条数等信息

18.step flow

一个Job顺序执行Job中各step,通过配置step的next属性,指定下一个步骤,

19.条件流程

spring batch通过设置step元素的on属性来支持条件流程,on属性取值为step的结束状态,特殊指定一种结束状态时,需要为step添加一个监听器,以返回指定的结束状态。

<step id="payStep">
    <tasklet>
        <chunk reader="billDbReader" processor="payProcessor" writer="payDbWriter" commit-interval="5" chunk-completion-policy="" skip-limit="100">
            <skippable-exception-classes>
                <include class="org.springframework.batch.sample.MoneyNotEnoughException" />
            </skippable-exception-classes>
        </chunk>
    </tasklet>
    <next on="COMPLETED WITH SKIPS" to="messageStep"/>
	<listeners>
	    <listener ref="payStepCheckingListener"></listener>
	</listeners>
</step>
public class PayStepCheckingListener extends StepExecutionListenerSupport {
    @Override
    public ExitStatus afterStep(StepExecution stepExecution) {
        String exitCode = stepExecution.getExitStatus().getExitCode();
	if (!exitCode.equals(ExitStatus.FAILED.getExitCode()) && stepExecution.getSkipCount() > 0) {
            return new ExitStatus("COMPLETED WITH SKIPS");
        } else {
            return null;
	}
    }
}

20.流程决策

step的结束状态不足于满足较为复杂的条件流程,流程决策器结合JobExecution和StepExecution,需要实现:JobExecutionDecider接口

public class MessagesDecider implements JobExecutionDecider {
    public FlowExecutionStatus decide(JobExecution jobExecution,StepExecution stepExecution) {
        String exitCode = stepExecution.getExitStatus().getExitCode();
	if (!exitCode.equals(ExitStatus.FAILED.getExitCode()) && stepExecution.getSkipCount() > 0) {
	    return new FlowExecutionStatus("COMPLETED WITH SKIPS");
	} else {
	    return FlowExecutionStatus.COMPLETED;
	}
    }
}
<job id="billingJob" restartable="true">
    <step id="billingStep" next="payStep"></step>
    <step id="payStep" next="decider"></step>
    <decision id="decider" decider="messagesDecider">
        <next on="COMPLETED WITH SKIPS" to="messageStep" />
	<end on="COMPLETED" />
    </decision>
    <step id="messageStep"></step>
</job>

21.step内并发处理

通过设置step的task-executor属性,可以让当前的step以并发方式执行,通过throttle-limit设置并发线程数。

<step id="billingStep" next="payStep">
    <tasklet task-executor="taskExecutor" throttle-limit="5">
        <chunk reader="userDbReader" processor="billingProcessor"
		writer="billDbWriter" commit-interval="5" chunk-completion-policy="">
	</chunk>
    </tasklet>
</step>
<beans:bean id="taskExecutor"
    class="org.springframework.core.task.SimpleAsyncTaskExecutor">
</beans:bean>

22.主要任务执行器

SyncTaskExecutor 简单同步执行器
ThrottledTaskExecutor 该执行器为其他任意执行器的装饰类,并完成提供执行次数限制的功能 视被装饰的执行器而定
SimpleAsyncTaskExecutor 简单异步执行器,提供了一种最基本的异步执行实现
WorkManagerTaskExecutor 该类作为通过 JCA 规范进行任务执行的实现,其包含 JBossWorkManagerTaskExecutor 和 GlassFishWorkManagerTaskExecutor 两个子类
ThreadPoolTaskExecutor 线程池任务执行器

23.step间并发处理,split flow

<job id="billingJob" restartable="true">
    <step id="billingStep" next="splitStep">
        <tasklet task-executor="taskExecutor" throttle-limit="5">
	    <chunk reader="userDbReader" processor="billingProcessor"
                   writer="billDbWriter" commit-interval="5" chunk-completion-policy="">
	    </chunk>
	</tasklet>
    </step>
    <split id="splitStep" task-executor="taskExecutor"  next="decider">
        <flow>
            <step id="billingMessageStep">
		<tasklet>
                    <chunk reader="billDbReader" processor="billMessageItemProcessor"
			   writer="messageDbWriter" commit-interval="5" chunk-completion-policy="">
		    </chunk>
		</tasklet>
	    </step>
        </flow>
	<flow>
	    <step id="payStep">
	        <tasklet>
                    <chunk reader="billDbReader" processor="payProcessor"
                           writer="payDbWriter" commit-interval="5" chunk-completion-policy="" skip-limit="100">
                        <skippable-exception-classes>
                            <include class="org.springframework.batch.sample.MoneyNotEnoughException" />
                        </skippable-exception-classes>
		    </chunk>
		</tasklet>
	    </step>
	</flow>
    </split>
    <decision id="decider" decider="messagesDecider">
        <next on="COMPLETED WITH SKIPS" to="paymentMessageStep" />
	<end on="COMPLETED" />
    </decision>
    <step id="paymentMessageStep">
        <tasklet>
            <chunk reader="billArrearsDbReader" processor="messageProcessor"
		    writer="messageDbWriter" commit-interval="5" chunk-completion-policy="">
	    </chunk>
	</tasklet>
    </step>
</job>

注意:只有当split中所有step执行完毕之后,才会执行split元素的下一步,同时需要为split元素制定task-executor为并行执行器,默认为:SyncTaskExecutor,同步执行器。

24.partition step,分区step

可以将耗时的步骤分配到多个机器上执行。

<beans:bean name="step" class="org.springframework.batch.core.partition.support.PartitionStep">
    <beans:property name="partitionHandler">
        <beans:bean class="org.springframework.batch.core.partition.support.TaskExecutorPartitionHandler">
	    <beans:property name="step" ref="remoteStep" />
	    <beans:property name="gridSize" value="10" />
	    <beans:property name="taskExecutor" ref="taskExecutor" />
	</beans:bean>
    </beans:property>
    <beans:property name="stepExecutionSplitter">
        <beans:bean class="org.springframework.batch.core.partition.support.SimpleStepExecutionSplitter">
	    <beans:constructor-arg ref="jobRepository" />
	    <beans:constructor-arg ref="messageStep" />
	    <beans:constructor-arg ref="simplePartitioner" />
	</beans:bean>
    </beans:property>
    <beans:property name="jobRepository" ref="jobRepository" />
</beans:bean>
<step id="messageStep">
    <tasklet task-executor="taskExecutor">
        <chunk reader="messageReader" processor="messageProcessor"
		writer="messageWriter" commit-interval="5" chunk-completion-policy=""
	        retry-limit="2">
	    <retryable-exception-classes>
	        <include class="java.lang.RuntimeException" />
	    </retryable-exception-classes>
	</chunk>
    </tasklet>
</step>
<beans:bean id="remoteStep" class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">
    <beans:property name="serviceInterface" value="org.springframework.batch.core.Step" />
    <beans:property name="serviceUrl" value="${batch.remote.base.url}/steps/messageStep" />
</beans:bean>

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值