Spring Retry重試機制

aoho發表於2018-05-09

在呼叫第三方介面或者使用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 = 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的引數說明:

  • value:丟擲指定異常才會重試
  • include:和value一樣,預設為空,當exclude也為空時,預設所以異常
  • exclude:指定不處理的異常
  • maxAttempts:最大重試次數,預設3次
  • backoff:重試等待策略,預設使用@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 Retry重試機制

可以看到,三次之後丟擲了IllegalArgumentException異常。

當重試耗盡時,RetryOperations可以將控制傳遞給另一個回撥,即RecoveryCallback。Spring-Retry還提供了@Recover註解,用於@Retryable重試失敗後處理方法,此方法裡的異常一定要是@Retryable方法裡丟擲的異常,否則不會呼叫這個方法。

@Recover
public int recover(Exception e) {
    logger.warn("減庫存失敗!!!" + LocalTime.now());
    return totalNum;
}
複製程式碼

在Service中,加上如上的方法之後,進行測試。

Spring Retry重試機制

可以看到當三次重試執行完之後,會呼叫Recovery方法,也不會再次丟擲異常。

總結

本文主要講了在Spring Boot專案中的Spring-Retry簡單應用,主要是基於註解配置一些重試的策略,使用比較簡單。主要的適用場景為在呼叫第三方介面或者使用mq時。由於會出現網路抖動,連線超時等網路異常,這時就需要重試。

本文的程式碼: https://github.com/keets2012/Spring-Cloud_Samples/tree/master/springboot-retry

訂閱最新文章,歡迎關注我的公眾號

微信公眾號

參考

  1. springboot 整合retry(重試機制)

相關文章