서버와 서버간 API 호출 실패에 대한 재시도는 매우 중요한 행위이다. 1번의 네트워크 호출 실패로 서비스의 비지니스 로직을 모두 실패처리하거나 fallback 처리하는 것은 몇 번 다시 호출하는 것보다 큰 리소스 낭비가 될 수 있기 때문이다.
재처리를 할 때 보통 아래를 고려하게 된다.
Retry를 하는 방식에는 어노테이션 방식과 RetryTemplate방식이 있다.
// 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(
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();
}
@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