1. Retry Pattern 구현 소개

이번 강의에서는 Spring Cloud Gateway를 사용하여 Retry Pattern을 구현해보겠습니다. 이 패턴은 특정 요청이 실패할 경우, 자동으로 재시도하는 기능을 제공합니다. 이번 구현에서는 Loans 마이크로서비스에 Retry Pattern을 적용할 것입니다.

2. Spring Cloud Gateway에서 Retry Pattern 설정

먼저, Gateway Server 애플리케이션 클래스에서 Retry Pattern을 설정하겠습니다. Loans 마이크로서비스의 특정 경로에 대해 3번 재시도하는 로직을 추가할 것입니다.

2.1 Retry Filter 설정

아래는 Gateway Server 애플리케이션 클래스에서 Retry Pattern을 적용하는 코드입니다.

@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
    return builder.routes()
        .route("loans_route", r -> r.path("/easybank/loans/**")
            .filters(f -> f.addResponseHeader("X-Response-Time", Long.toString(System.currentTimeMillis()))
                          .retry(config -> config.setRetries(3) // 3번 재시도
                                               .setMethods(HttpMethod.GET) // GET 메서드에만 재시도 적용
                                               .setBackoff(firstBackoff -> Duration.ofMillis(100)) // 첫 백오프 시간
                                               .maxBackoff(Duration.ofMillis(1000)) // 최대 백오프 시간
                                               .factor(2) // 각 재시도 간의 백오프 시간을 두 배로 증가
                                               .applyOnPreviousBackoff(true) // 이전 백오프 시간을 기준으로 백오프 적용
                          ))
            .uri("lb://loans-ms"))
        .build();
}
  • setRetries(3): 총 3번의 재시도를 설정합니다.
  • setMethods(HttpMethod.GET): GET 메서드에 대해서만 재시도를 수행합니다. 다른 메서드 (POST, PUT, DELETE)는 제외합니다.
  • setBackoff(): 재시도 간의 백오프 시간을 설정합니다. 첫 번째 재시도는 100ms 후에, 두 번째 재시도는 200ms 후에, 세 번째 재시도는 400ms 후에 이루어집니다. 최대 백오프 시간은 1000ms로 설정되었습니다.

3. LoansController에서 로그 및 예외 처리 설정

이제 LoansController에 로그와 예외 처리를 추가하여 Retry Pattern이 어떻게 작동하는지 확인해 보겠습니다.

3.1 로그 추가

먼저, LoansController에서 로그를 추가하여 contact-info API가 몇 번 호출되는지 확인할 수 있도록 설정합니다.

@RestController
public class LoansController {

    private static final Logger logger = LoggerFactory.getLogger(LoansController.class);

    @GetMapping("/contact-info")
    public LoansDto getContactInfo() {
        logger.debug("Invoked loans contact-info API");
        // 비즈니스 로직 처리
        return new LoansDto(/* data */);
    }
}

3.2 예외 처리 추가

contact-info API에서 의도적으로 RuntimeException을 발생시켜 재시도 동작을 확인합니다.

@GetMapping("/contact-info")
public LoansDto getContactInfo() {
    logger.debug("Invoked loans contact-info API");
    throw new RuntimeException("Simulated Exception");
    // 아래 코드는 더 이상 실행되지 않음
    // return new LoansDto(/* data */);
}

이렇게 하면, Gateway ServerRuntimeException이 발생할 때마다 재시도를 시도하게 됩니다.

4. 애플리케이션 실행 및 테스트

4.1 애플리케이션 빌드 및 재시작

이제 변경된 내용을 테스트하기 위해 애플리케이션을 빌드하고, LoansGateway Server 애플리케이션을 재시작합니다.

# Loans 애플리케이션 빌드 및 재시작
./mvnw clean install -DskipTests
java -jar target/loans-ms.jar

# Gateway Server 애플리케이션 빌드 및 재시작
./mvnw clean install -DskipTests
java -jar target/gateway-server.jar

4.2 Postman을 사용한 테스트

Postman에서 Loans 마이크로서비스의 contact-info API를 호출하여 Retry Pattern을 테스트합니다.

  • 첫 번째 시나리오: RuntimeException 발생 시
    • API를 호출하면 즉시 예외가 발생하고, Gateway Server는 총 3번의 재시도를 시도하게 됩니다.
    • 로그를 확인하면, "Invoked loans contact-info API" 메시지가 총 4번 (초기 요청 + 3번 재시도) 출력됩니다.
Invoked loans contact-info API
Invoked loans contact-info API
Invoked loans contact-info API
Invoked loans contact-info API
  • 두 번째 시나리오: 타임아웃 시 (백오프 전략 적용)
    • 최초 백오프 시간은 100ms이며, 이후 재시도 간의 백오프 시간은 200ms, 400ms로 증가합니다. 최대 백오프 시간은 1000ms입니다.

5. 요약

이번 강의에서는 Spring Cloud Gateway를 활용하여 Retry Pattern을 구현하고, Loans 마이크로서비스에 적용해 보았습니다. Retry Pattern은 일시적인 네트워크 문제나 일시적 장애로 인한 실패를 극복하기 위해 매우 유용하며, 백오프 전략을 통해 시스템의 부담을 최소화할 수 있습니다.

6. 최종 코드

@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
    return builder.routes()
        .route("loans_route", r -> r.path("/easybank/loans/**")
            .filters(f -> f.addResponseHeader("X-Response-Time", Long.toString(System.currentTimeMillis()))
                          .retry(config -> config.setRetries(3)
                                               .setMethods(HttpMethod.GET)
                                               .setBackoff(firstBackoff -> Duration.ofMillis(100))
                                               .maxBackoff(Duration.ofMillis(1000))
                                               .factor(2)
                                               .applyOnPreviousBackoff(true)))
            .uri("lb://loans-ms"))
        .build();
}
profile
무슨 생각하며 사니

0개의 댓글

Powered by GraphCDN, the GraphQL CDN