이번 강의에서는 이미 구현된 Retry Pattern
을 더욱 개선하는 방법을 다룹니다. 현재 getBuildInfo()
메서드에서 발생하는 모든 예외에 대해 재시도 작업이 수행됩니다. 하지만 특정 예외(예: NullPointerException
)에 대해서는 재시도를 하지 않도록 요구될 수 있습니다. 이러한 시나리오를 처리하는 방법을 배우겠습니다.
특정 예외가 발생할 때 재시도를 하지 않도록 설정하려면 application.yml
파일에서 ignoreExceptions
속성을 사용합니다.
ignoreExceptions
설정application.yml
파일에서 ignoreExceptions
를 추가하여 NullPointerException
이 발생했을 때 재시도하지 않도록 설정합니다.
resilience4j:
retry:
configs:
default:
max-attempts: 3
wait-duration: 100ms
exponential-backoff:
enabled: true
multiplier: 2
ignoreExceptions:
- java.lang.NullPointerException
ignoreExceptions
: 여기서 NullPointerException
을 무시하도록 설정했습니다. 즉, 이 예외가 발생할 경우 재시도하지 않습니다.반대로, 특정 예외에 대해서만 재시도를 수행하도록 설정할 수도 있습니다. 이 경우 retryExceptions
속성을 사용합니다.
retryExceptions
설정이번에는 TimeoutException
이 발생할 때만 재시도를 수행하도록 설정합니다.
resilience4j:
retry:
configs:
default:
max-attempts: 3
wait-duration: 100ms
exponential-backoff:
enabled: true
multiplier: 2
retryExceptions:
- java.net.SocketTimeoutException
retryExceptions
: 여기서는 SocketTimeoutException
에 대해서만 재시도를 수행하도록 설정했습니다. 이 설정이 적용되면 다른 예외가 발생할 경우 재시도가 수행되지 않습니다.AccountsController
에서 TimeoutException
을 던져서 재시도가 수행되는지 확인합니다.
TimeoutException
던지기@GetMapping("/build-info")
@Retry(name = "getBuildInfo", fallbackMethod = "getBuildInfoFallback")
public String getBuildInfo() throws TimeoutException {
logger.debug("Invoked getBuildInfo method");
throw new TimeoutException("Simulated Timeout Exception");
}
public String getBuildInfoFallback(Throwable t) {
logger.debug("Invoked getBuildInfoFallback method due to: " + t.getMessage());
return "0.9"; // fallback으로 반환할 버전 정보
}
TimeoutException
을 던져서, 해당 예외에 대해서만 재시도하는 동작을 확인합니다.Gateway Server
에서도 특정 예외에 대해 재시도를 수행할 수 있습니다. 예외 기반 재시도를 설정하려면 setExceptions()
메서드를 사용합니다.
Gateway Server
에서 재시도 예외 설정@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route("loans", r -> r.path("/loans/**")
.filters(f -> f
.retry(config -> config
.setRetries(3)
.setBackoff(Duration.ofMillis(100), Duration.ofSeconds(1), 2, true)
.setExceptions(SocketTimeoutException.class)
.setStatuses(HttpStatus.INTERNAL_SERVER_ERROR))
)
.uri("lb://loans"))
.build();
}
setExceptions(SocketTimeoutException.class)
: 이 설정을 통해 SocketTimeoutException
이 발생할 때만 재시도를 수행합니다.setStatuses(HttpStatus.INTERNAL_SERVER_ERROR)
: 특정 HTTP 상태 코드에 대해서도 재시도를 수행할 수 있습니다.이전에 Gateway Server에서 Retry Pattern
을 테스트할 때, 동일한 Correlation ID
가 응답 헤더에 여러 번 추가되는 문제가 있었습니다. 이 문제를 해결하기 위해, 조건문을 추가하여 동일한 헤더가 여러 번 추가되지 않도록 수정합니다.
@Component
public class ResponseTraceFilter extends AbstractGatewayFilterFactory<ResponseTraceFilter.Config> {
public static class Config {
// Configuration properties (if any) for the filter can go here.
}
public ResponseTraceFilter() {
super(Config.class);
}
@Override
public GatewayFilter apply(Config config) {
return (exchange, chain) -> {
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
if (!exchange.getResponse().getHeaders().containsKey(CORRELATION_ID_HEADER)) {
exchange.getResponse().getHeaders().add(CORRELATION_ID_HEADER, UUID.randomUUID().toString());
}
}));
};
}
}
if (!exchange.getResponse().getHeaders().containsKey(CORRELATION_ID_HEADER))
: 이 조건문을 통해 이미 존재하는 헤더를 중복 추가하지 않도록 했습니다.애플리케이션을 빌드하고 재시작하여 변경 사항을 반영합니다.
./mvnw clean install -DskipTests
java -jar target/accounts-ms.jar
java -jar target/gateway-server.jar
build-info
API를 Postman에서 호출하여 변경된 동작을 확인합니다.
이번 강의에서는 Retry Pattern
을 더욱 정교하게 구현하기 위해 ignoreExceptions
와 retryExceptions
를 활용하는 방법을 배웠습니다. 또한, Gateway Server에서의 예외 기반 재시도 설정과 응답 헤더 중복 문제를 해결하는 방법도 다루었습니다. 이 모든 설정을 통해 마이크로서비스의 안정성과 신뢰성을 크게 향상시킬 수 있습니다.
추가적으로, 이 모든 설정과 개념을 문서화하여 필요한 경우 언제든지 참조할 수 있도록 정리했습니다.
@RestController
public class AccountsController {
private static final Logger logger = LoggerFactory.getLogger(AccountsController.class);
@GetMapping("/build-info")
@Retry(name = "getBuildInfo", fallbackMethod = "getBuildInfoFallback")
public String getBuildInfo() throws TimeoutException {
logger.debug("Invoked getBuildInfo method");
throw new TimeoutException("Simulated Timeout Exception");
}
public String getBuildInfoFallback(Throwable t) {
logger.debug("Invoked getBuildInfoFallback method due to: " + t.getMessage());
return "0.9";
}
}
resilience4j:
retry:
configs:
default:
max-attempts: 3
wait-duration: 100ms
exponential-backoff:
enabled: true
multiplier: 2
retryExceptions:
- java.net.SocketTimeoutException
이 강의를 통해 Retry Pattern
의 다양한 설정과 적용 방법을 익힐 수 있었기를 바랍니다. 다음 강의에서도 중요한 패턴들을 다룰 예정이니 기대해 주세요.