[retry] spring-retry 다시 복기
springframework에서 제공하는 spring retry에 대해 알아보자
maven repo: https://mvnrepository.com/artifact/org.springframework.retry/spring-retry
spring aspect 라이브러리를 사용할 수도 있는데, 해당 라이브러리는 springboot starter에 있을 수 있기에 한번 확인하고 넣는 게 좋다.
springboot2.7.3 기준 5.3.24 버전이 들어가 있다.
관련 어노테이션을 사용하려면 아래처럼 enable 시켜줘야 한다.
import org.springframework.context.annotation.Configuration;
import org.springframework.retry.annotation.EnableRetry;
@Configuration
@EnableRetry
public class AppConfig {
}
실행 원리는 proxy!!
재시도를 해야 하는 함수에 @Retryable을 달아주고
재시도 시 실행해야하는 함수에 @Recover를 달아준다.
import org.springframework.retry.annotation.Recover;
import org.springframework.stereotype.Service;
@Service
public class MyService {
@Retryable(value = { SomeTransientException.class }, maxAttempts = 3)
public void performTask() throws SomeTransientException {
// Your logic here
System.out.println("Trying to perform task...");
throw new SomeTransientException("Temporary failure");
}
@Recover
public void recover(SomeTransientException e) {
// Recovery logic here
System.out.println("Recovering from failure: " + e.getMessage());
}
}
api에러 뿐만 아니라 아래와 같이 디비 에러에도 가능. IO에러 등등 많이 커버한다.. @Retryable에서 throw 하는 에러 타입과 @Recover에서 받는 에러타입이 반드시 같아야 한다.
@Service
public interface MyService {
@Retryable(retryFor = SQLException.class)
void retryServiceWithRecovery(String sql) throws SQLException;
@Recover
void recover(SQLException e, String sql);
}
Retryable 어노테이션에는 어떤 exception이 발생할 때 재시도를 할지와 최대 몇 번 실행할지를 지정해 줄 수 있다.
- maxAttempts: 실패가 n번 나면 recover 함수를 실행한다.
- default: 3
- backoff: 재실행하고 n초 쉬었다가 재실행(단위: ms)
- default: a fixed delay of 1000ms
- multiplier: 재시도와 재시도 사이의 시간 간극이 n배로 점점 멀어짐
- default: 0(무시)
- BackOffPolicy: 아래처럼 설정 값들에 따라 재시도 간격이 달라진다.
- With no explicit settings the default is a fixed delay of 1000ms
- Only the delay() set: the backoff is a fixed delay with that value
- When delay() and maxDelay() are set the backoff is uniformly distributed between the two values
- With delay(), maxDelay() and multiplier() the backoff is exponentially growing up to the maximum value
- If, in addition, the random() flag is set then the multiplier is chosen for each delay from a uniform distribution in [1, multiplier-1]
위 값들은 클래스에서 상수 값으로 관리할 수 있지만 공용사용과 환경별 관리를 위헤 프로퍼티 파일로 뺄 수도 있다.
이때 해당 변수 명이 달라지니(ex. maxAttemps -> maxAtempsExpression) 반드시 공식문서를 참고해야 한다!
공통 설정 혹은 더 복잡한 설정을 위해 java config로 설정할 수도 있다.
@Configuration
@EnableRetry
public class RetryConfig {
@Bean
public RetryTemplate retryTemplate(){
RetryTemplate retryTemplate = new RetryTemplate();
FixedBackOffPolicy fixedBackOffPolicy = new FixedBackOffPolicy();
fixedBackOffPolicy.setBackOffPeriod(3000l);
retryTemplate.setBackOffPolicy(fixedBackOffPolicy);
Map<Class<? extends Throwable>, Boolean> includeExceptions = new HashMap<>();
includeExceptions.put(CannotAcquireLockException.class, true);
SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy(5, includeExceptions);
retryTemplate.setRetryPolicy(retryPolicy);
return retryTemplate;
}
}
참고로 delay는 간격은 랜덤으로도 줄 수 있다.
@Retryable(
value = {CannotAcquireLockException.class},
maxAttempts = 4,
backoff = @Backoff(random = true, delay = 1000, maxDelay = 5000, multiplier = 2)
기본설명:
https://www.baeldung.com/spring-retry
좀더 복잡하게 사용하기:
https://medium.com/@vmoulds01/springboot-retry-random-backoff-136f41a3211a
이럴 수가.. 적으면서 이거 전에 본적 있는데 싶었는데 무려 정리를 했던 적이 있던 것ㅋㅋㅋㅋ
2022.02.04 - [개발/spring] - [retry] spring-retry for auto retry
[retry] spring-retry for auto retry
spring-retry? exception이 난 작업에 대해 자동으로 재시도 해주는 스프링 라이브러리이다. 일시적인 connection error 등에 유용하게 사용할 수 있다. 환경: springboot2.6.2 implementation 'org.springframework.retry:spri
bangpurin.tistory.com