반응형
본 내용은 인프런의 이도원 님의 강의 "Spring Cloud로 개발하는 마이크로서비스 애플리케이션(MSA)" 내용을 바탕으로 정리한 내용입니다.
기존 MSA 문제점
- A 서비스에서 B서비스를 호출할 때 B 서비스에 문제가 생기면 A 서비스에도 오류가 발생하는 현상이 생김
- ex) OrederService를 기동하지 않고 UserSerivce에서 호출하면 UnknownHostException 발생
- CircuitBreaker를 사용하여 오류 발생한 서비스를 재호출하지 않도록 변경
CircuitBreaker란?
- 마이크로서비스 아키텍처나 분산 시스템에서 자주 사용되는 패턴으로, 네트워크나 외부 서비스 호출 시 재 호출을 막고 시스템의 안정성을 높여 장애 확산을 방지하는 데 사용된다.
CircuitBreaker 의 목적
- 실패 격리: 서비스나 기능이 실패할 경우 해당 요청을 격리하여 시스템 전체로 전파되지 않도록 한다.
- 성능 보호: 반복적인 실패 시도를 줄여 시스템 리소스를 보호한다.
- 복구 기능 제공: 일정 시간이 지나거나 실패 원인이 해결되면 다시 정상적인 요청을 재개한다.
Circuit Breaker의 상태
- Closed (닫힘): 정상 상태로, 모든 요청을 통과시킨다. 실패가 발생해도 계속 시도한다.
- Open (열림): 일정 횟수 이상의 실패가 발생하면 열림 상태로 전환되는데 이 상태에서는 모든 요청을 즉시 실패로 처리하여 외부 서비스나 기능에 대한 호출을 중단한다.
- Half-Open (반 열림): 일정 시간이 지나면 다시 일부 요청을 허용하여 외부 서비스나 기능이 정상적으로 복구되었는지 확인하고 이 시점에 성공하면 다시 Closed 상태로 전환되고, 실패하면 다시 Open 상태로 돌아간다.
Resilience4j란?
- Java 애플리케이션을 위한 고가용성 라이브러리로, 특히 분산 시스템에서의 안정성과 복원력을 높이는 다양한 패턴을 제공한다.
- 각 패턴을 개별 모듈로 제공하여 필요에 따라 선택적으로 사용할 수 있다.
- Resilience4j의 Circuit Breaker는 특정 서비스 호출이 실패하면 일정 시간 동안 추가 호출을 차단하고, 그 후에 다시 일부 호출을 허용하여 서비스가 복구되었는지 확인한다.
실습
UserService
pom.xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-circuitbreaker-resilience4j</artifactId>
</dependency>
- resilience4j Dependency 추가
UserServiceImpl.class
@Autowired
private CircuitBreakerFactory circuitBreakerFactory;
/**
* 사용자 ID로 사용자 정보 조회
* @param userId
* @return
*/
@Override
public UserDto getUserByUserId(String userId) {
UserEntity userEntity = userRepository.findByUserId(userId);
if(userEntity == null) {
throw new UsernameNotFoundException("User not found");
}
UserDto userDto = new ModelMapper().map(userEntity, UserDto.class);
// circuitBreaker 추가
List<ResponseOrder> orderList = circuitBreaker.run(() -> orderServiceClient.getOrders(userId)
, throwable -> new ArrayList<>());
userDto.setOrders(orderList);
return userDto;
}
- CircuitBreakerFactory 추가
- CircuitBreaker 를 사용하여 외부 서비스 호출 실패 시 빈 ArrayList를 반환하도록 변경하여 오류가 발생하지 않게 한다.
결과 확인
- OrderService를 기동하지 않고 UserService 기동 후 http://127.0.0.1:8080/userService/users/${user_id} 호출 주문 정보 가져오는 로직에서 기동이 안된 OrderService 때문에 오류가 발생했지만
CircuitBreaker
추가 후 빈 리스트 orders를 반환하는 것을 볼 수 있다.
CircuitBreaker 커스터 마이징
Resilience4JConfiguration.class
package com.example.UserService.config;
import io.github.resilience4j.circuitbreaker.CircuitBreakerConfig;
import io.github.resilience4j.timelimiter.TimeLimiterConfig;
import org.springframework.cloud.circuitbreaker.resilience4j.Resilience4JCircuitBreakerFactory;
import org.springframework.cloud.circuitbreaker.resilience4j.Resilience4JConfigBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
import java.time.Duration;
@Configuration
public class Resilience4JConfiguration {
@Bean
public Customizer<Resilience4JCircuitBreakerFactory> globalCustomConfiguration() {
CircuitBreakerConfig circuitBreakerConfig = CircuitBreakerConfig.custom()
.failureRateThreshold(4)
.waitDurationInOpenState(Duration.ofMillis(1000))
.slidingWindowType(CircuitBreakerConfig.SlidingWindowType.COUNT_BASED)
.slidingWindowSize(2)
.build();
TimeLimiterConfig timeLimiterConfig = TimeLimiterConfig.custom()
.timeoutDuration(Duration.ofSeconds(4))
.build();
return factory -> factory.configureDefault(id -> new Resilience4JConfigBuilder(id)
.timeLimiterConfig(timeLimiterConfig)
.circuitBreakerConfig(circuitBreakerConfig)
.build());
}
}
- CircuitBreaker를 커스터 마이징 한다.
- failureRateThreshold(4): Circuit Breaker가 open 상태로 전환되는 실패 비율의 임계값을 4%로 설정
- waitDurationInOpenState(Duration.ofMillis(1000)): Circuit Breaker가 open 상태로 유지되는 시간을 1초로 설정
- slidingWindowType(CircuitBreakerConfig.SlidingWindowType.COUNT_BASED): 슬라이딩 윈도우를 호출 수 기준으로 설정
- slidingWindowSize(2): 슬라이딩 윈도우 크기를 2로 설정
- timeoutDuration(Duration.ofSeconds(4)): 서비스 호출의 타임아웃 시간을 4초로 설정
- Resilience4JConfigBuilder(id): 주어진 ID를 사용하여 Resilience4J 설정을 빌드
- timeLimiterConfig(timeLimiterConfig): 위에서 정의한 Time Limiter 설정을 적용
- circuitBreakerConfig(circuitBreakerConfig): 위에서 정의한 Circuit Breaker 설정을 적용
반응형
'Cloud > MSA' 카테고리의 다른 글
[MSA] Micrometer (1) | 2024.12.02 |
---|---|
[MSA] MSA 분산 추적 (0) | 2024.12.02 |
[MSA] Kafka Connect (0) | 2024.12.02 |
[MSA] Apache Kafka (0) | 2024.12.02 |
[MSA] Feign Client (0) | 2024.12.02 |