
아키텍처 에서는 서비스 간의 상호작용이 복잡해짐에 따라
장애 전파나 과부하 등의 문제가 발생할 수 있습니다.
이를 해결하기 위해 애플리케이션의 안정성을 강화하는 다양한 패턴이 사용되는데,
대표적인 라이브러리로 Resilience4j가 있습니다.
이번 포스팅에서는 Resilience4j를 사용해 Spring Boot 애플리케이션에서
Circuit Breaker, Rate Limiter, Retry를 적용하는 방법을 알아보겠습니다.
Resilience4j는 Java로 작성된 경량화된 라이브러리로,
MSA 환경에서 주로 사용되는 안정성 패턴을 구현할 수 있도록 도와줍니다.
주요 기능으로는 Circuit Breaker, Rate Limiter, Retry, Bulkhead 등이 있으며,
각 기능을 독립적으로 사용할 수 있어 필요한 부분만 선택적으로 적용할 수 있습니다.
Circuit Breaker는 서킷 브레이커 패턴을 구현한 것으로, 외부 서비스 호출이 실패할 경우
연속된 실패를 방지하기 위해 호출을 차단하는 기능입니다.
설정한 조건을 만족하면 자동으로 서비스 호출을 차단하고,
일정 시간이 지나면 다시 호출을 허용합니다.
import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
@Service
public class MyService {
private final RestTemplate restTemplate;
public MyService(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
@CircuitBreaker(name = "myService", fallbackMethod = "fallback")
public String callExternalService() {
return restTemplate.getForObject("http://external-service/api/resource", String.class);
}
public String fallback(Throwable t) {
return "External service is unavailable. Please try again later.";
}
}
resilience4j:
circuitbreaker:
instances:
myService:
registerHealthIndicator: true
slidingWindowSize: 5
minimumNumberOfCalls: 5
failureRateThreshold: 50
waitDurationInOpenState: 10000
이 설정은 myService라는 이름의 서킷 브레이커를 정의하고,
서비스 호출이 일정 기준을 넘어서 실패할 경우 호출을 차단하는 방법을 규정합니다.
서킷 브레이커가 언제 열리고 닫히는지, 또 얼마나 기다린 후 다시 호출을 허용할지 등을
조정할 수 있습니다.
이 설정을 통해 시스템의 복원력을 강화하고 외부 서비스 실패 시 전체 시스템으로
문제를 확산시키지 않도록 할 수 있습니다.
resilience4j 설정 중 circuitbreaker 항목에 대한 상세한 설명을 드리겠습니다.
이 설정은 Spring Boot 애플리케이션에서 Resilience4j의 서킷 브레이커(Circuit Breaker)
기능을 구성하는 부분입니다.
각 항목이 어떤 역할을 하는지 하나씩 살펴보겠습니다.
설명: myService라는 이름의 서킷 브레이커 인스턴스를 정의합니다.
하나의 애플리케이션 내에서 여러 서비스에 대해 각각의 서킷 브레이커 인스턴스를
설정할 수 있습니다.
예시: 만약 여러 외부 API를 호출하는 서비스가 있다면, 각각에 대해 별도의 서킷 브레이커
인스턴스를 만들어야 합니다.
- 예를 들어 paymentService, orderService 등.
설명: 이 설정은 서킷 브레이커의 상태를 Spring Boot Actuator의 헬스 체크(Health Indicator)로 등록할지를 결정합니다.
true로 설정하면 Actuator 엔드포인트(/actuator/health)에서 서킷 브레이커의 상태를
모니터링할 수 있습니다.
활용: 애플리케이션의 헬스 체크를 통해 서킷 브레이커가 열린 상태인지,
닫힌 상태인지 확인할 수 있어 운영에 유용합니다.
설명: 서킷 브레이커의 슬라이딩 윈도우 크기를 설정합니다. 슬라이딩 윈도우는 서킷 브레이커가 최근 몇 번의 호출을 기준으로 상태를 결정하는지를 나타냅니다.
여기서는 5로 설정되어 있어, 최근 5번의 호출을 기준으로 서킷 브레이커가 열릴지 닫힐지를 결정하게 됩니다.
추가 설명: 슬라이딩 윈도우에는 카운트 기반과 시간 기반 두 가지가 있습니다.
이 설정은 호출 수에 따른 카운트 기반의 슬라이딩 윈도우를 의미합니다.
설명: 실패율 임계치를 백분율로 설정합니다.
설정된 슬라이딩 윈도우 내에서 실패율이 이 임계치를 넘으면 서킷 브레이커가 열리게 됩니다.
여기서는 실패율이 50% 이상일 경우 서킷 브레이커가 열립니다.
예시: 만약 5번의 호출 중 3번이 실패하면 실패율이 60%가 되어 서킷 브레이커가 열립니다.
설명: 서킷 브레이커가 열린 상태에서 얼마나 기다릴지를 설정합니다.
이 값은 밀리초(ms) 단위로 지정되며, 여기서는 10,000밀리초(10초) 동안
서킷 브레이커가 열린 상태로 유지됩니다.
10초가 지나면 서킷 브레이커는 다시 반쯤 열린 상태(half-open)가 되어
새로운 시도를 받아들입니다.
활용: 이 설정을 통해 일시적인 문제를 가진 외부 서비스가 일정 시간 후 정상화될 때 다시 연결을 시도할 수 있습니다.
Rate Limiter는 주어진 시간 내에 호출 횟수를 제한하는 기능을 제공합니다.
이를 통해 서비스가 과도한 요청으로 인해 과부하되는 것을 방지할 수 있습니다.
import io.github.resilience4j.ratelimiter.annotation.RateLimiter;
import org.springframework.stereotype.Service;
@Service
public class MyRateLimitedService {
@RateLimiter(name = "myRateLimitedService", fallbackMethod = "rateLimiterFallback")
public String processRequest() {
// 요청 처리 로직
return "Request processed.";
}
public String rateLimiterFallback(Throwable t) {
return "Rate limit exceeded. Please try again later.";
}
}
resilience4j:
ratelimiter:
instances:
myRateLimitedService:
limitForPeriod: 10
limitRefreshPeriod: 1s
timeoutDuration: 1000ms
Retry는 외부 서비스 호출이 실패했을 때, 지정된 횟수만큼 재시도하는 기능입니다.
이는 일시적인 네트워크 장애나 서비스 불안정성으로 인한 실패를 극복하는 데 유용합니다.
import io.github.resilience4j.retry.annotation.Retry;
import org.springframework.stereotype.Service;
@Service
public class MyRetryService {
@Retry(name = "myRetryService", fallbackMethod = "retryFallback")
public String callExternalServiceWithRetry() {
// 외부 서비스 호출 로직
return "External service response";
}
public String retryFallback(Throwable t) {
return "Service is temporarily unavailable. Please try again later.";
}
}
resilience4j:
retry:
instances:
myRetryService:
maxAttempts: 3
waitDuration: 500ms
Resilience4j의 핵심 기능인 Circuit Breaker, Rate Limiter, Retry를
Spring Boot 애플리케이션에 적용하는 방법을 살펴보았습니다.
이러한 패턴을 사용하면 시스템의 안정성을 높이고 장애에 더욱 유연하게
대응할 수 있습니다.
Resilience4j는 설정과 사용법이 간단하면서도 강력한 기능을 제공하므로,
설계할 때 꼭 고려해볼 만한 라이브러리입니다.