在調用第三方接口或者使用mq時,會出現網絡抖動,連接配接逾時等網絡異常,是以需要重試。為了使處理更加健壯并且不太容易出現故障,後續的嘗試操作,有時候會幫助失敗的操作最後執行成功。例如,由于網絡故障或資料庫更新中的DeadLockLoserException導緻Web服務或RMI服務的遠端調用可能會在短暫等待後自行解決。 為了自動執行這些操作的重試,Spring Batch具有RetryOperations政策。不過該重試功能從Spring Batch 2.2.0版本中獨立出來,變成了Spring Retry子產品。
引入依賴
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
</dependency>
需要引入Spring-retry和aspectjweaver的依賴。
入口類
@SpringBootApplication
@EnableRetry
public class SpringbootRetryApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootRetryApplication.class, args);
}
}
入口類上開啟retry的攔截,使用
@EnableRetry
注解。
Service
@Service
public class PayService {
private Logger logger = LoggerFactory.getLogger(getClass());
private final int totalNum = ;
@Retryable(value = Exception.class, maxAttempts = , backoff = @Backoff(delay = L, multiplier = ))
public int minGoodsnum(int num) throws Exception {
logger.info("減庫存開始" + LocalTime.now());
try {
int i = / ;
} catch (Exception e) {
logger.error("illegal");
}
if (num <= ) {
throw new IllegalArgumentException("數量不對");
}
logger.info("減庫存執行結束" + LocalTime.now());
return totalNum - num;
}
}
@Retryable
的參數說明:
- value:抛出指定異常才會重試
- include:和value一樣,預設為空,當exclude也為空時,預設是以異常
- exclude:指定不處理的異常
- maxAttempts:最大重試次數,預設3次
- backoff:重試等待政策,預設使用
,@Backoff
的value預設為1000L,我們設定為2000L;multiplier(指定延遲倍數)預設為0,表示固定暫停1秒後進行重試,如果把multiplier設定為1.5,則第一次重試為2秒,第二次為3秒,第三次為4.5秒。@Backoff
測試類
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringbootRetryApplicationTests {
@Autowired
private PayService payService;
@Test
public void payTest() throws Exception {
int store = payService.minGoodsnum(-);
System.out.println("庫存為:" + store);
}
}
運作的控制台結果如下:

可以看到,三次之後抛出了
IllegalArgumentException
異常。
當重試耗盡時,RetryOperations可以将控制傳遞給另一個回調,即RecoveryCallback。Spring-Retry還提供了@Recover注解,用于@Retryable重試失敗後處理方法,此方法裡的異常一定要是@Retryable方法裡抛出的異常,否則不會調用這個方法。
@Recover
public int recover(Exception e) {
logger.warn("減庫存失敗!!!" + LocalTime.now());
return totalNum;
}
在Service中,加上如上的方法之後,進行測試。
可以看到當三次重試執行完之後,會調用Recovery方法,也不會再次抛出異常。
總結
本文主要講了在Spring Boot項目中的Spring-Retry簡單應用,主要是基于注解配置一些重試的政策,使用比較簡單。主要的适用場景為在調用第三方接口或者使用mq時。由于會出現網絡抖動,連接配接逾時等網絡異常,這時就需要重試。
本文的代碼: https://github.com/keets2012/Spring-Cloud_Samples/tree/master/springboot-retry
訂閱最新文章,歡迎關注我的公衆号
參考
- springboot 整合retry(重試機制)