Spring Retry 가 무엇일까?
다른 서버에게 API 호출 하였을때 1번의 실패로 서비스의 로직을 모두 실패하는것은 큰 리소스 낭비가 될수 있다.
틍정 API 호출 실패 상황에서는 최대 3번의 호출 재시도를 하는 등을 많이 쓰는것으로 알고 있다.
왜 재 시도를 하는지 예시로 들어보자면 일시적장애로 Read Timeout 이나 api throttling 문제가 재시도를 해볼만한 상황이다. 즉, 실패할경우 재시도를 몇번 하고 몇초 간격으로 다시 request 를 보낼수 있는지 다 실패할 경우에도 처리가 가능하게 지원해주는것이 Spring Retry 이다.
Spring Retry Template
나는 어노테이션을 쓰면서 배우고 있지만 Template 를 통해 똑같이 또는 설정하여 만들수 있다.
자세한건 공식 문서를 확인해보자. https://github.com/spring-projects/spring-retry
Spring Retry annotation
Retry 어노테이션은 간단하다.
다만, Config 파일을 만들어 @EnableRetry 라는 어노테이션을 붙여야 한다.
@Retryable 어노테이션을 쓰게 되면 defalut 로는 재시도는 최대 3번, 딜레이는 1초로 설정되어 있다.
하지만 이것은 변경할수 있다.
@Retryable( value = Exception.class, maxAttempts = 3, backoff = @Backoff(delay = 2000))
위와 같이 어떤 에러를 발생했을때 또한 몇번을 하고 몇초 마다 request 할 건지에 대한 설정이다.
이제 만약 3번다 실패할 경우를 @Recover 를 통해 처리 할 수 있다. 자세한건 아래의 예제를 보자.
예제 + 테스트 코드
직접 한번 KaKaoAPI 를 이용해서 고의로 에러 발생하여 실패하게 만들어 실행을 해보았다.
일단 먼저 RetryConfig 파일을 통해 설정해줘야 된다.
@EnableRetry
@Configuration
public class RetryConfig {
}
또한, 아래와 같이 딜레이 2초로 최대 3번까지 할수 있게 해놓고 만약 전부 실패 할 경우 null 를 반환하도록 하였다.
테스트를 위해 KakaoAK 를 KakaoAK1 로 설정 해놓고 아래와 같이 에러를 발생 하도록 하였다.
{
errorType: "AccessDeniedError",message: "cannot find Authorization : KakaoAK header"
}
@Retryable(
value = Exception.class,
maxAttempts = 3,
backoff = @Backoff(delay = 2000)
)
public KakaoMapApiResponse requestAddressSearch(String address) {
if (ObjectUtils.isEmpty(address)) return null;
HttpHeaders headers = new HttpHeaders();
headers.set(HttpHeaders.AUTHORIZATION, "KakaoAK1 " + kakaoApi);
HttpEntity http = new HttpEntity<>(headers);
ResponseEntity<KakaoMapApiResponse> sendKaKaoAPI = restTemplate.exchange(
buildUriByAddressSearch(address),
HttpMethod.GET,
http,
KakaoMapApiResponse.class
);
return sendKaKaoAPI.getBody();
}
@Recover
public KakaoMapApiResponse recover(Exception e, String address){
log.error("에러 나옴");
return null;
}
자 이제 테스트 코드를 작성하여 어떻게 처리가 되는지 확인해보자.
@Test
void 주소를주면카카오맵에서데이터를가져온다() {
String address = "경기도 의정부시 호원동";
KakaoMapApiResponse response = addressSearchService.requestAddressSearch(address);
assertNotNull("null체크", response);
}
실행할 경우 아래와 같은 출력이 나오게 된다.
위와 같이 3번을 2초간격으로 요청하지만 결국엔 전부 실패하여 @Recover 어노테이션인 달린 매서드에 log.error 가 찍히게 된다.
주의사항
@Retryable 리턴값, @Recover 의 리턴값 동일하게 맞추어 줘야 한다. 예제에서는 KakaoMapApiResponse 라는 DTO 파일을 만들어 처리 하였다. 만약 동일 하지 않다면 에러가 나오니 주의하자!
느낀점
서버와 서버의 요청 보낼때 안전고리 역할로 쓰면 좋을것 같다. 만약 쓰지않고 에러로 던지고 다시 request 하는 비용보다
저렇게 딜레이를 줘서 다시 response 받게 되서 처리하는것이 비용이 더 괜찮을것 같다고 생각이 들어 API 요청할때 주로 안전고리 역할로 쓸것 같다..!
'Spring' 카테고리의 다른 글
JWT (0) | 2023.06.26 |
---|---|
@Configuration 쓰고 안쓰고의 차이점 (0) | 2023.06.24 |
JPA Dirty Checking (0) | 2023.06.17 |
Hibernate (0) | 2023.06.13 |
JPA 구조 및 이론 (2) | 2023.06.13 |