이번 강의에서는 AccountsController
내부에서 Retry Pattern을 구현하는 방법을 다룹니다. 이전에는 Gateway Server
에서 Retry Pattern을 적용했지만, 개별 마이크로서비스에서도 이 패턴을 구현할 수 있습니다. 이번에는 build-info
API를 선택하여 Retry Pattern을 적용할 것입니다.
Retry Pattern을 설정하기 위해 @Retry
애노테이션을 사용합니다. 이 애노테이션을 통해 재시도 횟수와 fallback 메서드를 지정할 수 있습니다.
먼저, build-info
API에 Retry Pattern을 적용합니다.
@RestController
public class AccountsController {
@GetMapping("/build-info")
@Retry(name = "getBuildInfo", fallbackMethod = "getBuildInfoFallback")
public String getBuildInfo() {
logger.debug("Invoked getBuildInfo method");
throw new NullPointerException("Simulated Exception");
}
public String getBuildInfoFallback(Throwable t) {
logger.debug("Invoked getBuildInfoFallback method due to: " + t.getMessage());
return "0.9"; // fallback으로 반환할 버전 정보
}
}
@Retry(name = "getBuildInfo", fallbackMethod = "getBuildInfoFallback")
: 이 애노테이션은 build-info
API에 Retry Pattern을 적용합니다. getBuildInfo
라는 이름으로 패턴을 정의하며, 실패 시 호출될 fallback 메서드로 getBuildInfoFallback
을 지정합니다.getBuildInfoFallback(Throwable t)
: fallback 메서드로, 예외 발생 시 호출됩니다. 메서드 시그니처는 원래 메서드와 동일하게 유지하되, 추가로 Throwable
을 인자로 받아야 합니다.application.yml
파일에서 Retry Pattern에 대한 설정을 추가합니다.
resilience4j:
retry:
configs:
default:
max-attempts: 3 # 최대 3회 재시도
wait-duration: 500ms # 각 재시도 간 대기 시간
exponential-backoff:
enabled: true # 백오프 전략 사용
multiplier: 2 # 백오프 증가 비율
max-attempts: 3
: 최대 3번의 재시도를 허용합니다.wait-duration: 500ms
: 각 재시도 간 대기 시간을 500ms로 설정합니다.exponential-backoff
: 백오프 전략을 활성화하여, 각 재시도 시 대기 시간을 배수로 증가시킵니다.재시도 동작을 확인하기 위해 로그를 추가하고, NullPointerException
을 발생시킵니다.
@RestController
public class AccountsController {
private static final Logger logger = LoggerFactory.getLogger(AccountsController.class);
@GetMapping("/build-info")
@Retry(name = "getBuildInfo", fallbackMethod = "getBuildInfoFallback")
public String getBuildInfo() {
logger.debug("Invoked getBuildInfo method");
throw new NullPointerException("Simulated Exception");
}
public String getBuildInfoFallback(Throwable t) {
logger.debug("Invoked getBuildInfoFallback method due to: " + t.getMessage());
return "0.9"; // fallback으로 반환할 버전 정보
}
}
logger.debug()
를 사용하여 메서드가 호출될 때마다 로그를 출력합니다.NullPointerException
을 의도적으로 발생시켜, 재시도와 fallback 메서드 호출을 확인합니다.애플리케이션을 빌드하고 재시작합니다.
# Accounts 애플리케이션 빌드 및 재시작
./mvnw clean install -DskipTests
java -jar target/accounts-ms.jar
# Gateway Server 애플리케이션 빌드 및 재시작
./mvnw clean install -DskipTests
java -jar target/gateway-server.jar
Postman에서 build-info
API를 호출하여 Retry Pattern을 테스트합니다.
{
"response": "0.9"
}
RuntimeException
발생 시getBuildInfo
메서드가 3번 호출되고, 마지막으로 getBuildInfoFallback
이 호출됩니다.Invoked getBuildInfo method
Invoked getBuildInfo method
Invoked getBuildInfo method
Invoked getBuildInfoFallback method due to: Simulated Exception
만약 Circuit Breaker가 함께 사용된다면, Timeout 설정에 따라 Retry Pattern이 영향을 받을 수 있습니다. 기본적으로 Circuit Breaker는 특정 시간 내에 응답이 없으면 바로 fallback 메서드를 호출합니다. 이 경우 Retry 설정이 무시될 수 있습니다.
Circuit Breaker의 기본 Timeout 설정을 변경하여 Retry Pattern이 제대로 작동하도록 할 수 있습니다.
@Bean
public Customizer<ReactiveResilience4JCircuitBreakerFactory> defaultCustomizer() {
return factory -> factory.configureDefault(id -> new Resilience4JConfigBuilder(id)
.timeLimiterConfig(TimeLimiterConfig.custom()
.timeoutDuration(Duration.ofSeconds(4)) // Timeout을 4초로 설정
.build())
.circuitBreakerConfig(CircuitBreakerConfig.ofDefaults())
.build());
}
이번 강의에서는 AccountsController
에 Retry Pattern을 구현하고, 이 패턴이 제대로 작동하는지 확인하기 위해 여러 가지 설정을 추가했습니다. 또한 Circuit Breaker와 Retry Pattern이 어떻게 상호작용하는지에 대해서도 다루었습니다.
Retry Pattern을 통해 네트워크 장애와 같은 일시적인 문제를 처리할 수 있으며, Circuit Breaker와 함께 사용하여 마이크로서비스의 안정성을 더욱 강화할 수 있습니다.
@RestController
public class AccountsController {
private static final Logger logger = LoggerFactory.getLogger(AccountsController.class);
@GetMapping("/build-info")
@Retry(name = "getBuildInfo", fallbackMethod = "getBuildInfoFallback")
public String getBuildInfo() {
logger.debug("Invoked getBuildInfo method");
throw new NullPointerException("Simulated Exception");
}
public String getBuildInfoFallback(Throwable t) {
logger.debug("Invoked getBuildInfoFallback method due to: " + t.getMessage());
return "0.9";
}
}
이 강의를 통해 Retry Pattern을 개별 마이크로서비스에 적용하는 방법을 배웠으며, 이를 통해 마이크로서비스의 신뢰성을 높일 수 있었습니다. 다음 강의에서도 중요한 패턴들을 다룰 예정이니 기대해 주세요.