专栏名称: ImportNew
伯乐在线旗下账号,专注Java技术分享,包括Java基础技术、进阶技能、架构设计和Java技术领域动态等。
目录
相关文章推荐
芋道源码  ·  监控系统选型,一篇全搞定! ·  昨天  
芋道源码  ·  如何应对消息堆积? ·  2 天前  
Java编程精选  ·  WebSocket 的 6 ... ·  3 天前  
芋道源码  ·  Spring ... ·  2 天前  
芋道源码  ·  为了DDD 熬夜撸了一套 IDEA 插件) ·  2 天前  
51好读  ›  专栏  ›  ImportNew

SpringBatch 中的 retry 和 skip 机制实现分析

ImportNew  · 公众号  · Java  · 2017-04-12 12:05

正文

(点击 上方公众号 ,可快速关注)


来源:fangjian0423,

fangjian0423.github.io/2016/11/09/springbatch-retry-skip/#more

如有好文章投稿,请点击 → 这里了解详情


SpringBatch是spring框架下的一个子模块,用于处理批处理的批次框架。本文主要分析SpringBatch中的retry和skip机制的实现。


先简单说明下SpringBatch在SpringBoot中的使用。


如果要在springboot中使用batch的话,直接加入以下依赖即可:


org.springframework.boot

spring-boot-starter-batch


然后使用注解开启Batch模块:


...

@EnableBatchProcessing

public class Application { ... }


之后就可以注入JobBuilderFactory和StepBuilderFactory:


@Autowired

private JobBuilderFactory jobs;

@Autowired

private StepBuilderFactory steps;


有了这2个factory之后,就可以build job。


SpringBatch中的相关基础概念比如ItemReader、ItemWriter、Chunk等本文就不介绍了。


我们以FlatFileItemReader作为reader,一个自定义Writer用于打印reader中读取出来的数据。


这个定义的writer遇到good job这条数据的时候会报错,具体逻辑如下:


@Override

public void write(List extends String> items) throws Exception {

System.out.println("handle start =====" + items);

for(String a : items) {

if(a.equals("good job")) {

throw new Exception("custom exception");

}

}

System.out.println("handle end.. -----" + items);

}


其中reader中读取的文件中的数据如下:


hello world

hello coder

good job

cool

66666


我们使用StepBuilderFactory构造Step,chunkSize设置为2。然后在job1中使用并执行:


stepBuilderFactory.get("test-step").chunk(2).reader(reader).writer(writer).build();


执行job1后console打印如下:


handle start =====[hello world, hello coder]

handle end.. -----[hello world, hello coder]

handle start =====[good job, cool]


job1遇到了good job这条数据,writer抛出了异常,由于没有使用skip或者retry机制,导致整个流程停止。job1的处理流程底层在SimpleChunkProcessor这个类中完成,包括processor、writer的使用。


接下里我们构造一个job2,job2使用skip机制(其中skipLimit必须要和skip(Class extends Throwable> type)一起使用),skip机制可以防止writer发生异常后不停止整个job,但是需要同时满足skip的限制次数和skip对应的Exception是发生异常的父类或自身关系条件才不会停止整个job,这里我们使用Exception作为异常和Integer.MAX_VALUE作为skip的限制次数为例:


stepBuilderFactory.get.get("test-step").chunk(2).reader(reader).writer(writer).faultTolerant().skipLimit(Integer.MAX_VALUE).skip(Exception.class).build();


执行job2 后console打印如下:


handle start =====[hello world, hello coder]

handle end.. -----[hello world, hello coder]

handle start =====[good job, cool]

handle start =====[good job]

handle start =====[cool]

handle end.. -----[cool]

handle start =====[66666]

handle end.. -----[66666]


我们看到good job这条数据发生的异常被skip掉了,job完整的执行。


但是发现了另外一个问题,那就是处理 [good job, cool] 这批数据的时候,发生了异常,但是接下来执行了 [good job] 和 [cool] 这两批chunk为1的批次。这是在ItemWriter中执行的,它也会在ItemWriteListener中执行多次。


换句话说,如果使用了skip功能,那么对于需要被skip的批次数据中会进行scan操作找出具体是哪1条数据的原因,这里的scan操作指的是一条一条数据的遍历。


这个过程为什么叫scan呢? 在源码中,FaultTolerantChunkProcessor类(处理带有skip或者retry机制的处理器,跟SimpleChunkProcessor类似,只不过SimpleChunkProcessor处理简单的Job)里有个私有方法scan:







请到「今天看啥」查看全文


推荐文章
芋道源码  ·  监控系统选型,一篇全搞定!
昨天
芋道源码  ·  如何应对消息堆积?
2 天前
Java编程精选  ·  WebSocket 的 6 种集成方式,你知道几种?
3 天前
芋道源码  ·  为了DDD 熬夜撸了一套 IDEA 插件)
2 天前
南方周末  ·  山西惊现“酸湖”
8 年前
科学松鼠会  ·  看熊大人作大死:火焰旋涡升天啦!
7 年前
心理语录  ·  人和人,合则来,不合则散。
7 年前