内如主要来自以下链接:
- http://www.importnew.com/26177.html
- http://www.infoq.com/cn/articles/analysis-of-large-data-batch-framework-spring-batch
- spring batch批处理框架(书名)非常推荐!!!写得非常好!!!
一.spring batch介绍
什么是批处理:
在信息系统中,联机和批处理是计算机处理的两种基本模式。同联机模式汗牛充栋的著作、框架相比,批处理抽象模式的抽象不多,著名的MapReduce就是其中之一。spring batch将批处理程序分解为job和job step两个部分,将处理环节定义为数据读、数据处理和数据写三个步骤,将异常处理机制归结为跳过、重试和重启三种类型,将作业方式区分为多线程、并行、远程和分区四大特征。下图是一个典型的批处理应用:
调用spring batch的几种方式:可以通过web、命令行和调度框架,方式为同步(等待批处理完成)和异步调用。
二.spring batch三层架构:应用层、核心层和基础架构层
其中几个关键词的描述如下:
三.spring batch批处理框架
spring batch框架如上图,框架一共有4个主要角色:JobLauncher是任务启动器,通过它来启动任务,可以看做是程序的入口。Job代表着一个具体的任务。Step代表着一个具体的步骤,一个Job可以包含多个Step(想象把大象放进冰箱这个任务需要多少个步骤你就明白了)。JobRepository是存储数据的地方,可以看做是一个数据库的接口,在任务执行的时候需要通过它来记录任务状态等等信息。
- JobLauncher
JobLauncher是任务启动器,该接口只有一个run方法。除了传入Job对象之外,还需要传入JobParameters对象,后续讲到Job再解释为什么要多传一个JobParameters。通过JobLauncher可以在Java程序中调用批处理任务,也可以通过命令行或者其他框架(如定时调度框架Quartz、Web后台框架Spring MVC)中调用批处理任务。Spring Batch框架提供了一个JobLauncher的实现类SimpleJobLauncher。
- Job
Job代表着一个任务,一个Job与一个或者多个Job Instance相关联,而一个Job Instance又与一个或者多个Job Execution相关联:
考虑到任务可能不是只执行一次就再也不执行了,更多的情况可能是定时任务,如每天执行一次,每个星期执行一次等等,那么为了区分每次执行的任务,框架使用了JobInstance。如上图所示,Job是一个EndOfDay(每天最后时刻执行的任务),那么其中一个JobInstance就代表着2007年5月5日那天执行的任务实例。框架通过在执行JobLauncher.run(Job, JobParameters)方法时传入的JobParameters来区分是哪一天的任务。由于2007年5月5日那天执行的任务可能不会一次就执行完成,比如中途被停止,或者出现异常导致中断,需要多执行几次才能完成,所以框架使用了JobExecution来表示每次执行的任务。
- Step
一个Job任务可以分为几个Step步骤,与JobExection相同,每次执行Step的时候使用StepExecution来表示执行的步骤。每一个Step还包含着一个ItemReader、ItemProcessor、ItemWriter,下面分别介绍这三者。
- ItemReader:ItemReader代表着读操作,框架已经提供了多种ItemReader接口的实现类,包括对文本文件、XML文件、数据库、JMS消息等读的处理,当然我们也可以自己实现该接口。下图:FlatFileItemReader将Flat文件中的记录转换为java对象。对应写的话,就是将java对象转化为记录。
- ItemProcessor:ItemReader代表着处理操作,process方法的形参传入I类型的对象,通过处理后返回O型的对象。开发者可以实现自己的业务代码来对数据进行处理。
- ItemWriter:ItemReader代表着写操作,框架已经提供了多种ItemWriter接口的实现类,包括对文本文件、XML文件、数据库、JMS消息等写的处理,当然我们也可以自己实现该接口。
FlatFileItemReader的组件如下图:
lines to skip:需要跳过多少行,一般文件的一开始,第一行为标题,可以设置跳过第一行。
line mapper:将一行转换为一个java对象,主要依赖两个组件:linetokenizer-将一行拆分成多个字段;fieldsetmapper-将字段值构造成一个java对象。
StaxEventItemReader 提供了从XML输入流进行记录处理的典型设置。
按照面向chunk的操作,如果提交间隔(commit-interval)是3次,那么读操作被调用3次,写操作被调用1次。
支持非顺序的step,如下图:
- JobRepository
JobRepository用于存储任务执行的状态信息,比如什么时间点执行了什么任务、任务执行结果如何等等。框架提供了2种实现,一种是通过Map形式保存在内存中,当Java程序重启后任务信息也就丢失了,并且在分布式下无法获取其他节点的任务执行情况;另一种是保存在数据库中,并且将数据保存在下面6张表里,包括Job、Step的实例,上下文,执行器信息,为后续的监控、重启、重试、状态恢复等提供了可能:
- BATCH_JOB_INSTANCE:作业实例表,用于存放Job的实例信息
- BATCH_JOB_EXECUTION_PARAMS:作业参数表,用于存放每个Job执行时候的参数信息,该参数实际对应Job实例的。
- BATCH_JOB_EXECUTION:作业执行器表,用于存放当前作业的执行信息,比如创建时间,执行开始时间,执行结束时间,执行的那个Job实例,执行状态等。
- BATCH_STEP_EXECUTION:作业步执行器表,用于存放每个Step执行器的信息,比如作业步开始执行时间,执行完成时间,执行状态,读写次数,跳过次数等信息。
- BATCH_JOB_EXECUTION_CONTEXT:作业执行上下文表,用于存放作业执行器上下文的信息。
- BATCH_STEP_EXECUTION_CONTEXT:作业步执行上下文表,用于存放每个作业步上下文的信息。
这6张表的创建脚本可以从以下图中得到:
因为我的数据库是oracle,所以选下图红框中的,打开就可以看到数据库的创建脚本
四.作业的健壮性和扩展性
批处理要求Job必须有较强的健壮性,通常Job是批量处理数据、无人值守的,这要求在Job执行期间能够应对各种发生的异常、错误,并对Job执行进行有效的跟踪。一个健壮的Job通常需要具备如下的几个特性:
- 容错性:在Job执行期间非致命的异常,Job执行框架应能够进行有效的容错处理,而不是让整个Job执行失败;通常只有致命的、导致业务不正确的异常才可以终止Job的执行。
- 可追踪性:Job执行期间任何发生错误的地方都需要进行有效的记录,方便后期对错误点进行有效的处理。例如在Job执行期间任何被忽略处理的记录行需要被有效的记录下来,应用程序维护人员可以针对被忽略的记录后续做有效的处理。
- 可重启性:Job执行期间如果因为异常导致失败,应该能够在失败的点重新启动Job;而不是从头开始重新执行Job。
框架提供了支持上面所有能力的特性,包括Skip(跳过记录处理)、Retry(重试给定的操作)、Restart(从错误点开始重新启动失败的Job):
- Skip:在对数据处理期间,如果数据的某几条的格式不能满足要求,可以通过Skip跳过该行记录的处理,让Processor能够顺利的处理其余的记录行。
- Retry:将给定的操作进行多次重试,在某些情况下操作因为短暂的异常导致执行失败,如网络连接异常、并发处理异常等,可以通过重试的方式避免单次的失败,下次执行操作时候网络恢复正常,不再有并发的异常,这样通过重试的能力可以有效的避免这类短暂的异常。
- Restart:在Job执行失败后,可以通过重启功能来继续完成Job的执行。在重启时候,批处理框架允许在上次执行失败的点重新启动Job,而不是从头开始执行,这样可以大幅提高Job执行的效率。但仍需要保证job instance的状态不能为completed。
Spring Batch Admin中有一系列工具JobService,用以取消正在进行执行的任务。
五.线程安全性