Spring Batch 跳過策略配置
Spring batch job執行過程中遇到任何錯誤,默認情況下將使得相應步驟執行失敗。但有些場景我們希望跳過造成特定異常的當前處理項。本文探討Spring batch 提供的兩種方法配置跳過邏輯。
1.示例環境說明
爲了簡化說明,本文重用Spring Batch 入門教程 中的示例,實現把csv文件中的一些財務數據轉換爲xml格式。
但我們增加一些錯誤數據:
username, user_id, transaction_date, transaction_amount
devendra, 1234, 31/10/2015, 10000
john, 2134, 3/12/2015, 12321
robin, 2134, 2/02/2015, 23411
, 2536, 3/10/2019, 100
mike, 9876, 5/11/2018, -500
, 3425, 10/10/2017, 9999
最後三行有一些無效數據,其中第5、7行沒有username字段,第6行金額值爲負數。下面章節我們的目標就是配置讓批處理程序跳過這些錯誤數據。
2. 跳過限制和該跳過異常的配置
2.1. 使用skip 和 skipLimit方法
下面先討論第一中方法,使用skip 和 skipLimit方法實現執行失敗時跳過處理項。
@Bean
public Step skippingStep(ItemProcessor<Transaction, Transaction> processor, ItemWriter<Transaction> writer) throws ParseException {
return stepBuilderFactory
.get("skippingStep")
.<Transaction, Transaction>chunk(10)
.reader(itemReader(invalidInputCsv))
.processor(processor)
.writer(writer)
.faultTolerant()
.skipLimit(2)
.skip(MissingUsernameException.class)
.skip(NegativeAmountException.class)
.build();
}
首先需要啓用skip功能,需要在構建步驟時包括faultTolerant() 方法調用。在skip 和 skipLimit方法中,定義想跳過的異常類及最大跳過項數量。
上面示例中,如果在執行讀、處理或寫過程中無論遇到MissingUsernameException 或 NegativeAmountException 異常,當前正在處理的數據項被忽略並計數總數不超過2條。因此,第三次任何異常發生則整個執行失敗。
2.2. 使用noSkip方法
在前面示例中,任何其他類型異常(除了 MissingUsernameException 和 NegativeAmountException)仍會導致執行失敗。但有些場景指定異常發生執行步驟失敗而跳過任何其他異常更合適。
下面看如何使用skip, skipLimit, noSkip方法進行配置:
@Bean
public Step skippingStep( ItemProcessor<Transaction, Transaction> processor, ItemWriter<Transaction> writer) throws ParseException {
return stepBuilderFactory
.get("skippingStep")
.<Transaction, Transaction>chunk(10)
.reader(itemReader(invalidInputCsv))
.processor(processor)
.writer(writer)
.faultTolerant()
.skipLimit(2)
.skip(Exception.class)
.noSkip(SAXException.class)
.build();
}
這裏配置讓 Spring Batch除了SAXException異常外跳過任何異常,則意味着SAXException 異常總會引發步驟執行失敗。配置中skip() 和 noSkip() 順序沒有影響。
3. 使用自定義跳過策略
實際應用中可能需要更復雜的跳過檢查機制,因此Spring Batch框架提供了SkipPolicy 接口。我們可以實現自己的跳過邏輯並插入至步驟定義中。
繼續使用前面的示例,假如我們仍需定義最大跳過項爲2,僅跳過MissingUsernameException 和 NegativeAmountException 兩種異常。但再增加一個約束條件,僅當金額不超過一定限制時才能跳過NegativeAmountException異常。自定義的SkipPolicy實現如下:
public class CustomSkipPolicy implements SkipPolicy {
private static final int MAX_SKIP_COUNT = 2;
private static final int INVALID_TX_AMOUNT_LIMIT = -1000;
@Override
public boolean shouldSkip(Throwable throwable, int skipCount)
throws SkipLimitExceededException {
if (throwable instanceof MissingUsernameException && skipCount < MAX_SKIP_COUNT) {
return true;
}
if (throwable instanceof NegativeAmountException && skipCount < MAX_SKIP_COUNT ) {
NegativeAmountException ex = (NegativeAmountException) throwable;
if(ex.getAmount() < INVALID_TX_AMOUNT_LIMIT) {
return false;
} else {
return true;
}
}
return false;
}
}
現在我們能在定義步驟中使用自定義跳過策略:
@Bean
public Step skippingStep(
ItemProcessor<Transaction, Transaction> processor,
ItemWriter<Transaction> writer) throws ParseException {
return stepBuilderFactory
.get("skippingStep")
.<Transaction, Transaction>chunk(10)
.reader(itemReader(invalidInputCsv))
.processor(processor)
.writer(writer)
.faultTolerant()
.skipPolicy(new CustomSkipPolicy())
.build();
}
與前面配置類似,仍需要使用faultTolerant() 方法啓用跳過功能。但這次沒調用skip() 或 noSkip(),而是使用skipPolicy()方法並指定自定義的SkipPolicy 接口實現。
我們看到這種方法更加靈活,爲實際應用中理想選擇。
4. 總結
本文我們提供兩種方法實現Spring Batch的容錯處理功能。雖然使用skipLimit() 及 skip() 、noSkip()方法比較簡單,但使用自定義的SkipPolicy實現更強大、靈活。