在調用第三方接口或者使用mq時,會出現網絡抖動,鏈接超時等網絡異常,因此須要重試。爲了使處理更加健壯而且不太容易出現故障,後續的嘗試操做,有時候會幫助失敗的操做最後執行成功。例如,因爲網絡故障或數據庫更新中的DeadLockLoserException致使Web服務或RMI服務的遠程調用可能會在短暫等待後自行解決。 爲了自動執行這些操做的重試,Spring Batch具備RetryOperations策略。不過該重試功能從Spring Batch 2.2.0版本中獨立出來,變成了Spring Retry模塊。java
<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的依賴。git
@SpringBootApplication
@EnableRetry
public class SpringbootRetryApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootRetryApplication.class, args);
}
}
複製代碼
入口類上開啓retry的攔截,使用@EnableRetry
註解。github
@Service
public class PayService {
private Logger logger = LoggerFactory.getLogger(getClass());
private final int totalNum = 100000;
@Retryable(value = Exception.class, maxAttempts = 3, backoff = @Backoff(delay = 2000L, multiplier = 1.5))
public int minGoodsnum(int num) throws Exception {
logger.info("減庫存開始" + LocalTime.now());
try {
int i = 1 / 0;
} catch (Exception e) {
logger.error("illegal");
}
if (num <= 0) {
throw new IllegalArgumentException("數量不對");
}
logger.info("減庫存執行結束" + LocalTime.now());
return totalNum - num;
}
}
複製代碼
@Retryable
的參數說明:web
@Backoff
,@Backoff
的value默認爲1000L,咱們設置爲2000L;multiplier(指定延遲倍數)默認爲0,表示固定暫停1秒後進行重試,若是把multiplier設置爲1.5,則第一次重試爲2秒,第二次爲3秒,第三次爲4.5秒。@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringbootRetryApplicationTests {
@Autowired
private PayService payService;
@Test
public void payTest() throws Exception {
int store = payService.minGoodsnum(-1);
System.out.println("庫存爲:" + store);
}
}
複製代碼
運行的控制檯結果以下:spring
能夠看到,三次以後拋出了IllegalArgumentException
異常。數據庫
當重試耗盡時,RetryOperations能夠將控制傳遞給另外一個回調,即RecoveryCallback。Spring-Retry還提供了@Recover註解,用於@Retryable重試失敗後處理方法,此方法裏的異常必定要是@Retryable方法裏拋出的異常,不然不會調用這個方法。springboot
@Recover
public int recover(Exception e) {
logger.warn("減庫存失敗!!!" + LocalTime.now());
return totalNum;
}
複製代碼
在Service中,加上如上的方法以後,進行測試。 微信
能夠看到當三次重試執行完以後,會調用Recovery方法,也不會再次拋出異常。網絡
本文主要講了在Spring Boot項目中的Spring-Retry簡單應用,主要是基於註解配置一些重試的策略,使用比較簡單。主要的適用場景爲在調用第三方接口或者使用mq時。因爲會出現網絡抖動,鏈接超時等網絡異常,這時就須要重試。spring-boot
本文的代碼: https://github.com/keets2012/Spring-Cloud_Samples/tree/master/springboot-retry