引言 在實際的應用場景中,可能經常會遇到,當請求一個介面調一個服務的時候,出現異常或網路出現故障的情況下就會失敗,而對於那些重要的服務當失敗後,可能我們就會進行重試,多調用幾次,如果還是失敗再另外進行單獨處理。接下來,就是要講解的重點內容,我們可以通過@Retryable註解,優雅的實現迴圈重試功能 ...
引言
在實際的應用場景中,可能經常會遇到,當請求一個介面調一個服務的時候,出現異常或網路出現故障的情況下就會失敗,而對於那些重要的服務當失敗後,可能我們就會進行重試,多調用幾次,如果還是失敗再另外進行單獨處理。接下來,就是要講解的重點內容,我們可以通過@Retryable註解,優雅的實現迴圈重試功能。
1:引入依賴
<!-- spring-retry --> <dependency> <groupId>org.springframework.retry</groupId> <artifactId>spring-retry</artifactId> </dependency>
2:在啟動類上開啟retry重試功能
package com.patent.cloud; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.retry.annotation.EnableRetry; @SpringBootApplication @EnableRetry public class PatenCloudApplication { public static void main(String[] args) { SpringApplication.run(PatenCloudApplication.class, args); } }
3:業務處理,在要調用的方法上加上@Retryable註解
@Autowired private VehicleLocationDataService vehicleLocationDataService; /** * 需要在啟動類中添加@EnableRetry註釋以開啟重試功能,最後在相應的方法上添加@Retryable註解。 * @Recover註解,重試完成之後執行的回調方法 * 重試機制,如果調用方法過程中觸發了RuntimeException異常,則20秒後重試一次,最多重試3次,三次重試後會觸發recover方法 * @param orderNo * @param chassisNo * @param carStatus */ @GetMapping("/retryMyTest") @Retryable(value = RuntimeException.class,maxAttempts = 3, backoff = @Backoff(value = 10000L), recover = "recover", listeners = {"myRetryListener"}) public void retry(String orderNo, String chassisNo, String carStatus) throws RuntimeException { vehicleLocationDataService.retryMyTest(orderNo,chassisNo,carStatus); }
4:retryMyTest方法的邏輯處理
package com.patent.cloud.retry; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @Slf4j @Service public class VehicleLocationDataService { public static Integer retryCount = 1; public void retryMyTest(String orderNo, String chassisNo, String carStatus){ boolean flag = false; if("P8012985".equals(chassisNo)){ flag = true; } if(retryCount==4){ retryCount =1; } if(!flag){ log.info("有異常哦,我再試多幾次看下還有沒異常, 重試第{}次, {},{},{}",retryCount, orderNo,chassisNo,carStatus); retryCount ++; throw new RuntimeException("調用失敗!"); } } }
當程式出現RuntimeException的時候,就好觸發重試
5:recover方法,上邊定義了maxAttempts 為3,也就是說,重試三次後,如果還失敗了,則調用recover方法,需要在方法上標註@Recover註解
@Recover public void recover(RuntimeException runtimeException,String orderNo, String chassisNo, String carStatus) { log.info("=======觸發重試了recover方法======{}==={}=={}===",orderNo,chassisNo,carStatus); }
6:監聽,同時還是對重試方法進行了監聽,如我們在方法retry上,加了listeners 監聽
package com.patent.cloud.retry; import lombok.extern.slf4j.Slf4j; import org.springframework.retry.RetryCallback; import org.springframework.retry.RetryContext; import org.springframework.retry.listener.RetryListenerSupport; import org.springframework.stereotype.Service; @Slf4j @Service public class MyRetryListener extends RetryListenerSupport { @Override public <T, E extends Throwable> void close(RetryContext context, RetryCallback<T, E> callback, Throwable throwable) { log.info("監聽到重試過程關閉了"); log.info("======================================================================="); } @Override public <T, E extends Throwable> void onError(RetryContext context, RetryCallback<T, E> callback, Throwable throwable) { log.info("監聽到重試過程錯誤了"); } @Override public <T, E extends Throwable> boolean open(RetryContext context, RetryCallback<T, E> callback) { log.info("======================================================================="); log.info("監聽到重試過程開啟了"); return true; } }
7:運行結果