@Retryable, @Recover

Seung jun Cha·2023년 8월 27일
0

1. 개념

  • 서버와 서버간 API 호출 실패에 대한 재시도는 매우 중요한 행위이다. 1번의 네트워크 호출 실패로 서비스의 비지니스 로직을 모두 실패처리하거나 fallback 처리하는 것은 몇 번 다시 호출하는 것보다 큰 리소스 낭비가 될 수 있기 때문이다.

  • 재처리를 할 때 보통 아래를 고려하게 된다.

    • 재시도를 몇 번 실행할 것인가?
    • 재시도 하기 전에 지연시간을 얼마나 줄 것인가?
    • 재시도를 모두 실패했을 경우 어떻게 처리할 것인가?
  • Retry를 하는 방식에는 어노테이션 방식과 RetryTemplate방식이 있다.

2. @Retryable

  • @Retry를 사용할 수 있게 의존성을 추가한다. 여기서 mockWebServer는 외부API를 호출하는 메서드를 테스트하기 위해 사용한다. (ex 카카오 주소검색 API)
 // retry
    implementation 'org.springframework.retry:spring-retry'

 // mockWebServer
    testImplementation('com.squareup.okhttp3:okhttp:4.10.0')
    testImplementation('com.squareup.okhttp3:mockwebserver:4.10.0')
  • @Retryable의 사용방법은 아주 간단하다. 적용하려고 하는 메서드 위에 적기만 하면된다.
@Retryable(
            value = {RuntimeException.class}, // 어떤 예외가 발생했을 때, Retry를 할 것인지
            maxAttempts = 2,  // 재시도 횟수
            backoff = @Backoff(delay = 2000)  // 시도를 실패했을 때 다음 시도까지의 딜레이
    )
    public KakaoResponseDto requestAddressSearch(String address) {

        if (ObjectUtils.isEmpty(address)) {
            return null;
        }

        URI uri = kakaoUriBuilderService.buildUriByAddressSearch(address);
        HttpHeaders headers = new HttpHeaders();
        headers.set(HttpHeaders.AUTHORIZATION, "KakaoAK " + KakaoRestApiKey);
        HttpEntity httpEntity = new HttpEntity<>(headers);

        return restTemplate.exchange(uri, HttpMethod.GET, httpEntity, KakaoResponseDto.class).getBody();
    }

3. @Recover

  • @Retryable에서 정한 횟수만큼 시도한 후에도 정상작동 하지 않은 경우, @Recover를 적용한 메서드가 작동한다. 주의할 점은 @Retryable를 적용한 메서드와 @Recover를 적용한 메서드의 반환타입이 같아야 한다는 것이다. 아래의 예시 메서드는 그냥 로그만 출력했다.
 @Recover 
 public KakaoResponseDto recover(RuntimeException e, String address) {
        log.info("All retries failed. address = {} , error = {}", address, e.getMessage());
        return null;
    }

-참고
https://wonyong-jang.github.io/spring/2021/02/18/Spring-Retry.html

0개의 댓글