-
재시도 AOP스프링/스프링 AOP 2023. 9. 23. 21:48
단순 조회를 할 때 아주 가끔씩 간헐적으로 예외가 발생하는 경우가 있다. 단순 조회이기 때문에 그냥 새로고침을 눌러주면 된다. 이럴 때에는 재시도 AOP를 만들어서 예외가 가끔 발생하더라도 다시 재시도를 해주면 된다.
Retry 어노테이션
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface Retry { int value() default 3; }
Retry 어노테이션을 선언해줄 때 int value() default 3;이라는 변수를 선언해준다. 이 변수는 RetryAspect에서 재시도를 하는 default 값으로 사용될 것이다.
RetryAspect.class
@Slf4j @Aspect public class RetryAspect { @Around("@annotation(retry)") public Object doRetry(ProceedingJoinPoint joinPoint, Retry retry) throws Throwable { // 파라미터에 있는 Retry가 타입이라 @Around 안에가 대체 됨 log.info("[retry] {} retry={}", joinPoint.getSignature(), retry); int maxRetry = retry.value(); // 횟수 제한은 무조건 있어야함 Exception exceptionHolder = null; // 예외 담아두기 for (int retryCount = 1; retryCount <= maxRetry; retryCount++) { try { log.info("[retry] try count={}/{}", retryCount, maxRetry); return joinPoint.proceed(); } catch (Exception e) { exceptionHolder = e; } } throw exceptionHolder; } }
재시도를 해주는 aop이다. @Around의 경로는 doRetry의 파라미터 안에 있는 Retry 타입으로 대체할 수 있다.
로직을 보면 retry.value()에서 default 값인 3을 가져온 다음 maxRetry만큼 루프를 돈다.
이 때, 성공하면 joinPoint.proceed()를 return 한다.
exceptionHolder를 선언해주고 사용하고 있는데, 에러가 났을 때 catch를 해서 최후에 throw를 던져줄 수 있는 용도이다.
만약에 2번째까지 예외가 났을 때, 3번째에서 로직이 잘 수행되면 return joinPoint.proceed()로 인해 예외가 던져지지 않는다. 하지만 3번째까지 예외가 나면 joinPoint.proceed()를 반환하지 않아서 예외가 throw 된다.
@Repository public class ExamRepository { private static int seq = 0; /** * 5번에 1번 실패하는 요청 */ @Trace @Retry(4) // default(재시도) 값 여기서 바꿔줄 수 있음 public String save(String itemId) { seq++; if (seq % 5 == 0) { throw new IllegalStateException("예외 발생"); } return "ok"; } }
@Trace 밑에 @Retry 어노테이션을 붙여줘서 aop를 하나 더 걸어줬다. 어노테이션 안에 숫자를 넣어주면 default 값이 되어서 이 숫자만큼 재시도를 해주는 것이다.
@Slf4j @Import({TraceAspect.class, RetryAspect.class}) @SpringBootTest public class ExamTest { @Autowired ExamService examService; @Test void test() { for (int i = 0; i < 5; i++) { log.info("client request i={}", i); examService.request("data" + i); } } }
테스트코드를 실행해보면 로직이 제대로 설계되었는지 확인할 수 있다.
5번째인 data4에서 에러가 발생했지만 Retry aop로 인해서 재시도를 하게 되어서 예외가 발생하지 않고 정상 응답이 되었다.
재시도 aop를 사용할 때에는 무조건 default 값을 정해두어야 한다는 것을 명심해야한다.
'스프링 > 스프링 AOP' 카테고리의 다른 글
HTTP 요청 응답 기록 - httpexchanges (0) 2023.10.01 AOP 주의사항 - 프록시와 내부 호출 (0) 2023.09.23 어노테이션으로 AOP 사용 (0) 2023.09.23 포인트컷 - execution (0) 2023.09.23 어드바이스 종류 (0) 2023.09.22