自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

配置 Spring Batch 批處理失敗重試

開發(fā) 前端
默認情況下,Spring批處理作業(yè)在執(zhí)行過程中出現(xiàn)任何錯誤都會失敗。然而有些時候,為了提高應(yīng)用程序的彈性,我們就需要處理這類間歇性的故障。在這篇短文中,我們就來一起探討 如何在Spring批處理框架中配置重試邏輯。

[[357093]]

 1. 引言

默認情況下,Spring批處理作業(yè)在執(zhí)行過程中出現(xiàn)任何錯誤都會失敗。然而有些時候,為了提高應(yīng)用程序的彈性,我們就需要處理這類間歇性的故障。在這篇短文中,我們就來一起探討 如何在Spring批處理框架中配置重試邏輯。

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

開車!Spring Batch 入門級示例教程!

2. 簡單舉例

假設(shè)有一個批處理作業(yè),它讀取一個CSV文件作為輸入:

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

然后,它通過訪問REST端點來處理每條記錄,獲取用戶的 age 和 postCode 屬性:

  1. public class RetryItemProcessor implements ItemProcessor<TransactionTransaction> { 
  2.      
  3.     @Override 
  4.     public Transaction process(Transaction transaction) throws IOException { 
  5.         log.info("RetryItemProcessor, attempting to process: {}"transaction); 
  6.         HttpResponse response = fetchMoreUserDetails(transaction.getUserId()); 
  7.         //parse user's age and postCode from response and update transaction 
  8.         ... 
  9.         return transaction
  10.     } 
  11.     ... 

最后,它生成并輸出一個合并的XML:

  1. <transactionRecord> 
  2.     <transactionRecord> 
  3.         <amount>10000.0</amount> 
  4.         <transactionDate>2015-10-31 00:00:00</transactionDate> 
  5.         <userId>1234</userId> 
  6.         <username>sammy</username> 
  7.         <age>10</age> 
  8.         <postCode>430222</postCode> 
  9.     </transactionRecord> 
  10.     ... 
  11. </transactionRecord> 

3. ItemProcessor 中添加重試

現(xiàn)在假設(shè),如果到REST端點的連接由于某些網(wǎng)絡(luò)速度慢而超時,該怎么辦?如果發(fā)生這種情況,則我們的批處理工作將失敗。

在這種情況下,我們希望失敗的 item 處理重試幾次。因此,接下來我將批處理作業(yè)配置為:在出現(xiàn)故障時執(zhí)行最多三次重試:

  1. @Bean 
  2. public Step retryStep( 
  3.   ItemProcessor<TransactionTransaction> processor, 
  4.   ItemWriter<Transaction> writer) throws ParseException { 
  5.     return stepBuilderFactory 
  6.       .get("retryStep"
  7.       .<TransactionTransaction>chunk(10) 
  8.       .reader(itemReader(inputCsv)) 
  9.       .processor(processor) 
  10.       .writer(writer) 
  11.       .faultTolerant() 
  12.       .retryLimit(3) 
  13.       .retry(ConnectTimeoutException.class) 
  14.       .retry(DeadlockLoserDataAccessException.class) 
  15.       .build(); 

這里調(diào)用了 faultTolerant() 來啟用重試功能。另外,我們使用 retry 和 retryLimit 分別定義符合重試條件的異常和 item 的最大重試次數(shù)。

4. 測試重試次數(shù)

假設(shè)我們有一個測試場景,其中返回 age 和 postCode 的REST端點關(guān)閉了一段時間。在這個測試場景中,我們只對前兩個 API 調(diào)用獲取一個 ConnectTimeoutException ,而第三個調(diào)用將成功:

  1. @Test 
  2. public void whenEndpointFailsTwicePasses3rdTime_thenSuccess() throws Exception { 
  3.     FileSystemResource expectedResult = new FileSystemResource(EXPECTED_OUTPUT); 
  4.     FileSystemResource actualResult = new FileSystemResource(TEST_OUTPUT); 
  5.  
  6.     when(httpResponse.getEntity()) 
  7.       .thenReturn(new StringEntity("{ \"age\":10, \"postCode\":\"430222\" }")); 
  8.   
  9.     //fails for first two calls and passes third time onwards 
  10.     when(httpClient.execute(any())) 
  11.       .thenThrow(new ConnectTimeoutException("Timeout count 1")) 
  12.       .thenThrow(new ConnectTimeoutException("Timeout count 2")) 
  13.       .thenReturn(httpResponse); 
  14.  
  15.     JobExecution jobExecution = jobLauncherTestUtils 
  16.       .launchJob(defaultJobParameters()); 
  17.     JobInstance actualJobInstance = jobExecution.getJobInstance(); 
  18.     ExitStatus actualJobExitStatus = jobExecution.getExitStatus(); 
  19.  
  20.     assertThat(actualJobInstance.getJobName(), is("retryBatchJob")); 
  21.     assertThat(actualJobExitStatus.getExitCode(), is("COMPLETED")); 
  22.     AssertFile.assertFileEquals(expectedResult, actualResult); 

在這里,我們的工作成功地完成了。另外,從日志中可以明顯看出 第一條記錄 id=1234 失敗了兩次,最后在第三次重試時成功了:

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

同樣,看下另一個測試用例,當(dāng)所有重試次數(shù)都用完時會發(fā)生什么:

  1. @Test 
  2. public void whenEndpointAlwaysFail_thenJobFails() throws Exception { 
  3.     when(httpClient.execute(any())) 
  4.       .thenThrow(new ConnectTimeoutException("Endpoint is down")); 
  5.  
  6.     JobExecution jobExecution = jobLauncherTestUtils 
  7.       .launchJob(defaultJobParameters()); 
  8.     JobInstance actualJobInstance = jobExecution.getJobInstance(); 
  9.     ExitStatus actualJobExitStatus = jobExecution.getExitStatus(); 
  10.  
  11.     assertThat(actualJobInstance.getJobName(), is("retryBatchJob")); 
  12.     assertThat(actualJobExitStatus.getExitCode(), is("FAILED")); 
  13.     assertThat(actualJobExitStatus.getExitDescription(), 
  14.       containsString("org.apache.http.conn.ConnectTimeoutException")); 

在這個測試用例中,在作業(yè)因 ConnectTimeoutException 而失敗之前,會嘗試對第一條記錄重試三次。

5. 使用XML配置重試

最后,讓我們看一下與上述配置等價的XML:

  1. <batch:job id="retryBatchJob"
  2.     <batch:step id="retryStep"
  3.         <batch:tasklet> 
  4.             <batch:chunk reader="itemReader" writer="itemWriter" 
  5.               processor="retryItemProcessor" commit-interval="10" 
  6.               retry-limit="3"
  7.                 <batch:retryable-exception-classes> 
  8.                     <batch:include class="org.apache.http.conn.ConnectTimeoutException"/> 
  9.                     <batch:include class="org.springframework.dao.DeadlockLoserDataAccessException"/> 
  10.                 </batch:retryable-exception-classes> 
  11.             </batch:chunk> 
  12.         </batch:tasklet> 
  13.     </batch:step> 
  14. </batch:job> 

6. 簡單總結(jié)

在本文中,我們學(xué)習(xí)了如何在Spring批處理中配置重試邏輯,其中包括使用Java和XML配置。以及使用單元測試來觀察重試在實踐中是如何工作的。

本文轉(zhuǎn)載自微信公眾號「鍋外的大佬」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請聯(lián)系鍋外的大佬公眾號。

 

責(zé)任編輯:武曉燕 來源: 鍋外的大佬
相關(guān)推薦

2022-08-02 20:47:38

Spring框架應(yīng)用程序

2023-08-22 08:01:42

SpringBatch事務(wù)管理

2012-02-20 09:49:42

ibmdw

2017-01-12 14:50:15

大數(shù)據(jù)Spring Batc框架

2020-11-03 15:10:55

Spring Batc框架Java

2025-04-29 08:00:36

2009-07-22 16:43:22

iBATIS框架iBATIS優(yōu)化

2009-06-18 15:40:07

Spring Batc

2010-07-16 10:42:14

telnet批處理

2009-05-11 10:27:32

Spring Batc配置工作劃分

2024-05-29 09:20:41

2022-09-15 07:31:49

Spring攔截器注解

2023-11-27 07:44:59

RabbitMQ機制

2009-07-24 16:42:46

iBatis框架做ba

2022-03-01 14:55:39

數(shù)據(jù)庫Spring批處理

2021-02-20 10:02:22

Spring重試機制Java

2024-08-14 08:11:41

2013-02-22 14:35:38

2022-04-27 08:55:01

Spring外部化配置

2009-06-12 08:43:37

微軟Windows 7操作系統(tǒng)
點贊
收藏

51CTO技術(shù)棧公眾號