点击上方蓝色“方志朋”,选择“设为星标”

回复“666”获取独家整理的学习资料!

1. 引言

默认情况下,Spring批处理作业在执行过程中出现任何错误都会失败。然而有些时候,为了提高应用程序的弹性,我们就需要处理这类间歇性的故障。在这篇短文中,我们就来一起探讨 如何在Spring批处理框架中配置重试逻辑

如果对spring batch不了解,可以参考以前的一篇文章:

开车!Spring Batch 入门级示例教程!

2. 简单举例

假设有一个批处理作业,它读取一个CSV文件作为输入:

username, userid, transaction_date, transaction_amount
sammy, 1234, 31/10/2015, 10000
john, 9999, 3/12/2015, 12321

然后,它通过访问REST端点来处理每条记录,获取用户的 age 和 postCode 属性:

public class RetryItemProcessor implements ItemProcessor<Transaction, Transaction> {@Overridepublic Transaction process(Transaction transaction) throws IOException {log.info("RetryItemProcessor, attempting to process: {}", transaction);HttpResponse response = fetchMoreUserDetails(transaction.getUserId());//parse user's age and postCode from response and update transaction...return transaction;}...
}

最后,它生成并输出一个合并的XML

<transactionRecord><transactionRecord><amount>10000.0</amount><transactionDate>2015-10-31 00:00:00</transactionDate><userId>1234</userId><username>sammy</username><age>10</age><postCode>430222</postCode></transactionRecord>...
</transactionRecord>

3. ItemProcessor 中添加重试

现在假设,如果到REST端点的连接由于某些网络速度慢而超时,该怎么办?如果发生这种情况,则我们的批处理工作将失败。

在这种情况下,我们希望失败的 item 处理重试几次。因此,接下来我将批处理作业配置为:在出现故障时执行最多三次重试

@Bean
public Step retryStep(ItemProcessor<Transaction, Transaction> processor,ItemWriter<Transaction> writer) throws ParseException {return stepBuilderFactory.get("retryStep").<Transaction, Transaction>chunk(10).reader(itemReader(inputCsv)).processor(processor).writer(writer).faultTolerant().retryLimit(3).retry(ConnectTimeoutException.class).retry(DeadlockLoserDataAccessException.class).build();
}

这里调用了 faultTolerant() 来启用重试功能。另外,我们使用 retry 和 retryLimit 分别定义符合重试条件的异常和 item 的最大重试次数

4. 测试重试次数

假设我们有一个测试场景,其中返回 age 和 postCode 的REST端点关闭了一段时间。在这个测试场景中,我们只对前两个 API 调用获取一个 ConnectTimeoutException ,而第三个调用将成功:

@Test
public void whenEndpointFailsTwicePasses3rdTime_thenSuccess() throws Exception {FileSystemResource expectedResult = new FileSystemResource(EXPECTED_OUTPUT);FileSystemResource actualResult = new FileSystemResource(TEST_OUTPUT);when(httpResponse.getEntity()).thenReturn(new StringEntity("{ \"age\":10, \"postCode\":\"430222\" }"));//fails for first two calls and passes third time onwardswhen(httpClient.execute(any())).thenThrow(new ConnectTimeoutException("Timeout count 1")).thenThrow(new ConnectTimeoutException("Timeout count 2")).thenReturn(httpResponse);JobExecution jobExecution = jobLauncherTestUtils.launchJob(defaultJobParameters());JobInstance actualJobInstance = jobExecution.getJobInstance();ExitStatus actualJobExitStatus = jobExecution.getExitStatus();assertThat(actualJobInstance.getJobName(), is("retryBatchJob"));assertThat(actualJobExitStatus.getExitCode(), is("COMPLETED"));AssertFile.assertFileEquals(expectedResult, actualResult);
}

在这里,我们的工作成功地完成了。另外,从日志中可以明显看出 第一条记录 id=1234 失败了两次,最后在第三次重试时成功了

19:06:57.742 [main] INFO  o.s.batch.core.job.SimpleStepHandler - Executing step: [retryStep]
19:06:57.758 [main] INFO  o.b.batch.service.RetryItemProcessor - Attempting to process user with id=1234
19:06:57.758 [main] INFO  o.b.batch.service.RetryItemProcessor - Attempting to process user with id=1234
19:06:57.758 [main] INFO  o.b.batch.service.RetryItemProcessor - Attempting to process user with id=1234
19:06:57.758 [main] INFO  o.b.batch.service.RetryItemProcessor - Attempting to process user with id=9999
19:06:57.773 [main] INFO  o.s.batch.core.step.AbstractStep - Step: [retryStep] executed in 31ms

同样,看下另一个测试用例,当所有重试次数都用完时会发生什么:

@Test
public void whenEndpointAlwaysFail_thenJobFails() throws Exception {when(httpClient.execute(any())).thenThrow(new ConnectTimeoutException("Endpoint is down"));JobExecution jobExecution = jobLauncherTestUtils.launchJob(defaultJobParameters());JobInstance actualJobInstance = jobExecution.getJobInstance();ExitStatus actualJobExitStatus = jobExecution.getExitStatus();assertThat(actualJobInstance.getJobName(), is("retryBatchJob"));assertThat(actualJobExitStatus.getExitCode(), is("FAILED"));assertThat(actualJobExitStatus.getExitDescription(),containsString("org.apache.http.conn.ConnectTimeoutException"));
}

在这个测试用例中,在作业因 ConnectTimeoutException 而失败之前,会尝试对第一条记录重试三次。

5. 使用XML配置重试

最后,让我们看一下与上述配置等价的XML:

<batch:job id="retryBatchJob"><batch:step id="retryStep"><batch:tasklet><batch:chunk reader="itemReader" writer="itemWriter"processor="retryItemProcessor" commit-interval="10"retry-limit="3"><batch:retryable-exception-classes><batch:include class="org.apache.http.conn.ConnectTimeoutException"/><batch:include class="org.springframework.dao.DeadlockLoserDataAccessException"/></batch:retryable-exception-classes></batch:chunk></batch:tasklet></batch:step>
</batch:job>

6. 简单总结

在本文中,我们学习了如何在Spring批处理中配置重试逻辑,其中包括使用Java和XML配置。以及使用单元测试来观察重试在实践中是如何工作的。

热门内容:
  • 你知道Spring Boot项目是怎么启动的吗?

  • 那些总是写“烂代码”的同学,强烈推荐你用这款IDEA插件!

  • Spring-Retry重试实现原理

  • Spring Boot 中的 RestTemplate不好用?试试 Retrofit !

  • 监控系统选型,这篇不可不读!

最近面试BAT,整理一份面试资料《Java面试BAT通关手册》,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。获取方式:点“在看”,关注公众号并回复 666 领取,更多内容陆续奉上。
明天见(。・ω・。)ノ

配置 Spring Batch 批处理失败重试相关推荐

  1. 配置 Spring Batch 批处理失败重试机制

    1. 引言 默认情况下,Spring批处理作业在执行过程中出现任何错误都会失败.然而有些时候,为了提高应用程序的弹性,我们就需要处理这类间歇性的故障. 在这篇短文中,我们就来一起探讨 如何在Sprin ...

  2. [Spring Cloud Task]6 Spring Batch批处理应用设计原则

    2019独角兽企业重金招聘Python工程师标准>>> 概述 本文是Spring Cloud Task系列的第五篇文章,如果你尚未使用过Spring Cloud Task,请 移步s ...

  3. Spring Batch 批处理框架

    <Spring Batch 批处理框架> 基本信息 作者: 刘相 出版社:电子工业出版社 ISBN:9787121252419 上架时间:2015-1-24 出版日期:2015 年2月 开 ...

  4. java批处理框架 pdf_《Spring Batch 批处理框架》PDF 下载

    图书目录: 第1篇 入门篇 第1章 Spring Batch简介 1.1 什么是批处理 1.2 Spring Batch 1.2.1 典型场景 1.2.2 Spring Batch架构 1.3 Spr ...

  5. java批处理框架采集端_使用Spring Batch批处理框架(参考)

    本文主要介绍了春季批量框架的使用分析.文章通过实例代码详细介绍,对每个人的学习或工作都有一定的参考和学习价值,需要的朋友可以参考. 使用春季批处理作为批处理框架,可以在常规数据量不是特别大的情况下完成 ...

  6. 学会Spring Batch 批处理框架,效率翻倍,上班轻松又快乐

    一.SpringBatch 介绍 Spring Batch 是一个轻量级.全面的批处理框架,旨在支持开发对企业系统的日常操作至关重要的健壮的批处理应用程序.Spring Batch 建立在人们期望的 ...

  7. Spring Batch 配置重试逻辑

    Spring Batch 配置重试逻辑 Spring Batch在处理过程中遇到错误job默认会执行失败.为了提高应用程序的健壮性,我们需要处理临时异常造成失败.本文我们探讨如何配置Spring Ba ...

  8. 大数据批处理框架Spring Batch 的全面解析

    如今微服务架构讨论的如火如荼.但在企业架构里除了大量的OLTP交易外,还存在海量的批处理交易.在诸如银行的金融机构中,每天有3-4万笔的批处理作业需要处理.针对OLTP,业界有大量的开源框架.优秀的架 ...

  9. 数据批处理神器-Spring Batch(1)简介及使用场景

    数据批处理神器-Spring Batch(1)简介及使用场景 tags: springbatch 1.引言 最近使用Spring Batch进行做数据迁移.数据同步.数据批处理等工作,感叹Spring ...

最新文章

  1. android 保存 用户名和密码 设置等应用信息优化
  2. 为什么说特斯拉在自动驾驶上比Waymo更占优势
  3. 观点 | 有区块链就一定能创新吗?区块链改变了什么、改变不了什么?
  4. windows下使用lighttpd+php(fastcgi)+mysql
  5. 基于Mybatis,处理多表联合获取
  6. PDF文件使用指南(转载)
  7. 浅谈线程池(下):相关试验及注意事项
  8. C++Primer Plus (第六版)阅读笔记 + 源码分析【第一章:预备知识】
  9. Java精确到毫秒获取时间的三种方法,以及适用场景
  10. SAP Commerce(原Hybris)的订单处理框架和SAP CRM One Order框架
  11. 201521123014 《Java程序设计》第8周学习总结
  12. 教室信息管理系统mysql_教师信息管理系统(方式一:数据库为oracle数据库;方式二:存储在文件中)...
  13. Java集合系列---List源码解析(ArrayList和LinkedList的区别)
  14. Python工作笔记004---python字符串前面加上'r'的作用_u_b的含义
  15. RabbitMQ(7)-发后即忘模型
  16. PHP字体向右移动,CSS3如何实现文字向右循环闪过效果以及可在移动端使用的实例代码分享...
  17. 第二十一讲 ASP.NET页面框架
  18. 牛客网产品笔试题刷题打卡——用户研究/项目管理
  19. 为什么现代物理学离不开量子论和相对论?
  20. LLVM 编译器学习笔记之三十六-- 指令调度Instruction scheduling

热门文章

  1. SQL: ORA-00979 不是 GROUP BY 表达式 及 Group by 的用法说明
  2. 非结构化信息-》半结构化-》结构化-》关联数据体系-》数据挖掘-》故事化呈现-》决策导向
  3. 通过CPAN安装Perl模块
  4. 数据导出Excel表格
  5. Python 学习笔记: 反射
  6. [亲测]在Mac下配置php开发环境:Apache+php+MySql
  7. 7. Query Expressions(查询表达式)
  8. 数据结构与算法:14 Leetcode同步练习(五)
  9. 基于 Opencv 实现眼睛控制鼠标
  10. 用 Python 快速制作海报级地图