Resilience4j란?
Resilience4j는 Spring Boot 애플리케이션에서 회복력 있는 마이크로서비스를 구축하기 위해 설계된 경량 라이브러리입니다. Circuit Breaker, Rate Limiter, Retry, Bulkhead, Time Limiter와 같은 주요 패턴을 제공합니다. 각 패턴은 별도로 구현되며, 원하는 모듈만 선택해서 사용할 수 있는 장점이 있습니다.
주요 기능
- Circuit Breaker (회로 차단기)
서비스 호출 실패가 반복되면 회로를 열어 추가 실패를 방지하고, 일정 시간이 지나면 재시도를 허용합니다. - Rate Limiter (속도 제한기)
호출 횟수를 제한하여 서비스 과부하를 방지합니다. - Retry (재시도)
실패한 요청을 재시도하여 잠재적 네트워크 문제를 해결합니다. - Bulkhead (벌크헤드)
서비스의 스레드 및 리소스를 분리하여 한 서비스의 장애가 전체 시스템에 영향을 미치지 않도록 합니다. - Time Limiter (시간 제한기)
호출 시간이 초과되면 타임아웃 처리합니다.
1. 회로차단기 (Circuit Breaker)
개념
- 회로차단기는 연속된 실패를 감지하여 시스템 자원을 보호하기 위해 회로를 열어서 추가적인 요청을 차단합니다.
동작 원리
- Closed (닫힘): 서비스가 정상적으로 작동합니다. 실패율이 설정된 임계치를 초과하면 Open 상태로 전환됩니다.
- Open (열림): 모든 요청을 차단하며, 바로 실패로 응답합니다. 일정 시간이 지나면 Half-Open 상태로 변경됩니다.
- Half-Open (반열림): 일부 요청만 허용하여 서비스가 정상적으로 복구되었는지 확인합니다. 성공하면 Closed 상태로 돌아가고, 실패하면 Open 상태로 전환됩니다.
주요 설정
failureRateThreshold
: 회로를 열기 위한 실패율 임계치 (기본값: 50%).slidingWindowSize
: 실패율을 계산하는 기준이 되는 호출 수.waitDurationInOpenState
: Open 상태에서 Half-Open 상태로 전환되기 전 대기 시간.permittedNumberOfCallsInHalfOpenState
: Half-Open 상태에서 허용되는 호출 수.
적용 사례
- 외부 API 호출이 일정 횟수 이상 실패할 때 이를 차단하여 리소스를 보호.
YAML 설정 예시
resilience4j.circuitbreaker.instances.licenseService:
failureRateThreshold: 50
sliding-window-size: 100
waitDurationInOpenState: 10s
permitted-number-of-calls-in-half-open-state: 10
recordExceptions:
- org.springframework.web.client.HttpServerErrorException
- java.io.IOException
2. 재시도 (Retry)
개념
- 재시도는 요청이 실패했을 때 지정된 횟수만큼 다시 시도하는 기능입니다.
동작 원리
- 요청이 실패할 경우, 정의된 횟수만큼 재시도합니다.
- 재시도 간격 또는 대기 시간을 설정할 수 있습니다.
- 폴백 메서드를 통해 최종적으로 실패한 경우 대체 동작을 처리할 수 있습니다.
주요 설정
max-attempts
: 최대 재시도 횟수 (기본값: 3).waitDuration
: 각 재시도 사이의 대기 시간.retry-exceptions
: 재시도를 트리거하는 예외 목록.
적용 사례
- 네트워크 연결 문제로 인한 일시적인 실패를 처리.
YAML 설정 예시
resilience4j.retry.instances.retryLicenseService:
max-attempts: 5
waitDuration: 1000ms
retry-exceptions:
- java.util.concurrent.TimeoutException
코드 예시
@Retry(name = "retryLicenseService", fallbackMethod = "fallbackForRemoteCall")
public String callRemoteService() {
// 네트워크 호출
}
public String fallbackForRemoteCall(Exception e) {
return "Fallback response due to: " + e.getMessage();
}
3. 벌크헤드 (Bulkhead)
개념
- 벌크헤드는 시스템 자원을 분리하여 특정 서비스의 과부하가 다른 서비스에 영향을 미치지 않도록 방지합니다.
방식
- 스레드풀 방식: 서비스 요청을 처리하기 위해 별도의 스레드풀을 사용.
- 세마포어 방식: 동시 요청의 수를 제한.
주요 설정
- 스레드풀 방식:
max-thread-pool-size
: 스레드풀의 최대 크기.core-thread-pool-size
: 스레드풀의 기본 크기.queue-capacity
: 대기 큐의 크기.
- 세마포어 방식:
max-concurrent-calls
: 동시에 처리 가능한 요청 수.
적용 사례
- 특정 서비스가 과부하 상태가 되더라도 다른 서비스가 정상적으로 작동하도록 분리.
YAML 설정 예시
resilience4j.thread-pool-bulkhead.instances.bulkheadLicenseService:
max-thread-pool-size: 20
core-thread-pool-size: 10
queue-capacity: 10
4. 속도 제한 (Rate Limiter)
개념
- 단위 시간당 처리할 수 있는 요청의 수를 제한하여 시스템이 과부하 상태에 빠지지 않도록 합니다.
주요 설정
limitForPeriod
: 단위 시간당 허용되는 요청 수.limitRefreshPeriod
: 요청 제한을 초기화하는 주기.timeoutDuration
: 초과된 요청이 얼마나 대기할 수 있는지.
적용 사례
- API 호출을 제한하여 특정 서비스가 과부하 상태에 빠지지 않도록 보호.
YAML 설정 예시
resilience4j.ratelimiter.instances.licenseService:
limitForPeriod: 5
limitRefreshPeriod: 5000ms
timeoutDuration: 1000ms
5. 폴백 (Fallback)
개념
- 회로차단기와 재시도에서 모두 실패한 경우, 폴백을 통해 대체 동작을 수행합니다.
적용 사례
- 원격 호출 실패 시 기본값 반환 또는 캐시된 데이터 제공.
코드 예시
@Retry(name = "retryLicenseService", fallbackMethod = "fallbackForRemoteCall")
public String callExternalService() {
throw new RuntimeException("Service unavailable");
}
public String fallbackForRemoteCall(RuntimeException e) {
return "Fallback response: " + e.getMessage();
}
6. 캐싱 (Cache)
개념
- 동일한 요청에 대해 반복적으로 호출하지 않고 결과를 캐싱하여 성능을 최적화합니다.
주요 설정
cacheDuration
: 캐싱 기간.cacheCapacity
: 캐싱할 데이터의 최대 수.
적용 사례
- 데이터베이스나 원격 API의 빈번한 호출을 줄임.
YAML 설정 예시
resilience4j.cache.instances.cacheService:
cacheDuration: 10m
cacheCapacity: 100
정리
- 회로차단기 (Circuit Breaker): 연속된 실패 시 요청 차단.
- 재시도 (Retry): 요청 실패 시 재시도.
- 벌크헤드 (Bulkhead): 자원 분리로 과부하 방지.
- 속도 제한 (Rate Limiter): 초당 요청 수 제한.
- 폴백 (Fallback): 최종 실패 시 대체 동작 수행.
- 캐싱 (Cache): 동일한 요청 결과를 캐싱.
Resilience4j YML 설정 분석 (예제 참고)
1. Circuit Breaker
resilience4j.circuitbreaker:
instances:
licenseService:
registerHealthIndicator: true
sliding-window-size: 100
permitted-number-of-calls-in-half-open-state: 10
waitDurationInOpenState: 10s
failureRateThreshold: 50
recordExceptions:
- org.springframework.web.client.HttpServerErrorException
- java.io.IOException
- java.util.concurrent.TimeoutException
- org.springframework.web.client.ResourceAccessException
organizationService:
registerHealthIndicator: true
sliding-window-size: 6
permitted-number-of-calls-in-half-open-state: 4
waitDurationInOpenState: 20s
failureRateThreshold: 60
sliding-window-size
: 회로 차단기의 슬라이딩 윈도우 크기입니다. 최근 100개의 호출에 대해 성공/실패 비율을 평가합니다.permitted-number-of-calls-in-half-open-state
: 반열림(Half-Open) 상태에서 허용되는 호출 수.waitDurationInOpenState
: Open 상태가 유지되는 시간 (10초).failureRateThreshold
: 실패율 임계값입니다. 예를 들어, 실패율이 50% 이상이면 회로를 엽니다.recordExceptions
: 실패로 간주할 예외 목록.
구현 효과:licenseService
및 organizationService
호출에서 설정된 실패율과 조건에 따라 회로를 열어 서비스의 부하를 줄이고 안정성을 유지합니다.
2. Rate Limiter
resilience4j.ratelimiter:
instances:
licenseService:
limitForPeriod: 5
limitRefreshPeriod: 5000
timeoutDuration: 1000ms
limitForPeriod
: 제한된 시간 동안 허용되는 최대 호출 수 (5개).limitRefreshPeriod
: 호출 제한이 초기화되는 주기 (5초).timeoutDuration
: 제한 초과 시 대기하는 시간 (1초).
구현 효과:licenseService
호출이 과도하게 이루어지지 않도록 제한합니다. 5초마다 최대 5개의 호출만 허용합니다.
3. Retry
resilience4j.retry:
instances:
retryLicenseService:
max-attempts: 5
waitDuration: 10000
retry-exceptions:
- java.util.concurrent.TimeoutException
max-attempts
: 최대 재시도 횟수 (5회).waitDuration
: 재시도 간 대기 시간 (10초).retry-exceptions
: 특정 예외 발생 시에만 재시도를 수행합니다.
구현 효과:
타임아웃 예외 발생 시 요청을 최대 5회까지 재시도하여, 일시적인 네트워크 장애를 복구합니다.
4. Bulkhead (Thread Pool Bulkhead)
resilience4j:
thread-pool-bulkhead:
instances:
bulkheadLicenseService:
max-thread-pool-size: 20
core-thread-pool-size: 10
queue-capacity: 10
max-thread-pool-size
: 스레드풀의 최대 크기 (20).core-thread-pool-size
: 기본적으로 유지되는 스레드 수 (10).queue-capacity
: 대기 요청 큐의 최대 크기 (10).
구현 효과:licenseService
호출에 대한 병렬 스레드 수를 제한하여, 시스템 과부하를 방지합니다.
Resilience4j의 적용 방법
- YAML 설정: 위와 같은 YML 파일에서 원하는 모듈을 설정합니다.
- 의존성 추가:
<dependency> <groupId>io.github.resilience4j</groupId> <artifactId>resilience4j-spring-boot2</artifactId> </dependency>
- 애노테이션 적용:
- Circuit Breaker:
@CircuitBreaker(name = "licenseService", fallbackMethod = "fallbackMethod") public String licenseService() { // 비즈니스 로직 }
- Retry:
@Retry(name = "retryLicenseService") public String retryMethod() { // 재시도할 메서드 }
- 로그 모니터링: Actuator를 통해 회로 상태를 모니터링할 수 있습니다.
'MSA' 카테고리의 다른 글
Netflix Zuul ( API 게이트웨이 ) (1) | 2024.12.16 |
---|---|
폴백(Fallback) (0) | 2024.12.13 |
allow-bean-definition-overriding (1) | 2024.12.11 |
@ConfigurationProperties (0) | 2024.12.11 |
리프레시 스코프(Refresh Scope) (0) | 2024.12.11 |