[Spring Cloud] 장애 처리와 서비스 분산 추적

jsieon97·2023년 3월 22일
0

장애 처리

CircuitBreaker

UserService에 적용

Dependencies

implementation 'org.springframework.cloud:spring-cloud-starter-circuitbreaker-resilience4j'

Order를 가져오는 부분에서 오류가 생겼을 때 빈 리스트를 반환하도록 수정

// UserServiceImpl.java

@Service
@Slf4j
public class UserServiceImpl implements UserService {

    private UserRepository userRepository;
    private BCryptPasswordEncoder bCryptPasswordEncoder;
    private Environment env;
    private RestTemplate restTemplate;
    private OrderServiceClient orderServiceClient;
    private CircuitBreakerFactory circuitBreakerFactory;

    public UserServiceImpl(UserRepository userRepository,
                           BCryptPasswordEncoder bCryptPasswordEncoder,
                           Environment env,
                           RestTemplate restTemplate,
                           OrderServiceClient orderServiceClient,
                           CircuitBreakerFactory circuitBreakerFactory) {
        this.userRepository = userRepository;
        this.bCryptPasswordEncoder = bCryptPasswordEncoder;
        this.env = env;
        this.restTemplate = restTemplate;
        this.orderServiceClient = orderServiceClient;
        this.circuitBreakerFactory = circuitBreakerFactory;
    }

    ...

    @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);

        ...

        /* ErrorDecoder */
//        List<ResponseOrder> ordersList = orderServiceClient.getOrders(userId);

        /* CircuitBreaker */
        CircuitBreaker circuitBreaker = circuitBreakerFactory.create("circuitbreaker");
        List<ResponseOrder> ordersList = circuitBreaker.run(() -> orderServiceClient.getOrders(userId),
                throwable -> new ArrayList<>());

        userDto.setOrders(ordersList);

        return userDto;
    }

    ...
    
}
UserId기준으로 가져온 OrderList가 null이어도 오류가아닌 빈 List를 반환한다.

Resilience4J

  • 서킷 브레이커의 현재 상태를 마이크로 서비스 액추에이터 상태 점검 엔드 포인트(/actuator/health)를 사용해 모니터링할 수 있다.
  • 서킷 브레이커는 상태 전이 등의 이벤트 액추에이터 엔드 포인트(/actuator/citcuitbreakerevents)를 게시한다.
  • 서킷 브레이커 스프링 부트의 매트릭스 시스템과 통합돼 있으며 이를 이용해 프로테우스와 같은 모니터링 도구에 메트릭을 게시할 수 있다.
// Resilience4JConfig.java
// 서킷 브레이커의 설정파일

@Configuration
public class Resilience4JConfig {
    @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.ofMillis(4))
                .build();

        return factory -> factory.configureDefault(id -> new Resilience4JConfigBuilder(id)
                .timeLimiterConfig(timeLimiterConfig)
                .circuitBreakerConfig(circuitBreakerConfig)
                .build()
        );
    }
}

분산 추적

MSA 서비스에서 다른 서비스가 중지됨으로써 실행에 실패하는 것을 CircuitBreaker로 방지했다면 이제 분산 추적을 통해 어느 서비스끼리 통신하다 실패하였는지 추적을 해보자.

Zipkin

  • https://zipkin.io/
  • Twitter에서 사용하는 분산 환경의 Timing 데이터 수집, 추적 시스템 (오픈 소스)
  • Google Drapper에서 발전하였으며, 분산환경에서의 시스템 병목 현상 파악
  • Collector, Query Service, Databasem WebUI로 구성
  • Span
    • 하나의 요청에 사용되는 작업의 단위
    • 64 bit unique ID
  • Trace
    • 트리 구조로 이뤄진 Span 세서
    • 하나의 요청에 대한 같은 Trace ID 발급

Spring Cloud Sleuth

  • 스프링 부트 어플리케이션을 Zipkin과 연동
  • 요청 값에 따른 Trace ID, Span ID 부여
  • Trace와 Span Ids를 로그에 추가 가능
    • servlet filter
    • rest template
    • scheduled actions
    • message channels
    • feign client

Zipkin 설치

https://zipkin.io/pages/quickstart 에서

  • Windows의 경우 Running from Source 부분을 활용
  • Mac의 경우 Java 부분의 명령어 실행

Zipkin, Sleuth 사용

사용할 서비스에 Dependencies 추가

implementation 'org.springframework.cloud:spring-cloud-starter-sleuth'
implementation 'org.springframework.cloud:spring-cloud-starter-zipkin:2.2.3.RELEASE'

property 설정

// appication.yml

spring:
  application:
    name: user-service
  zipkin:
    base-url: http://127.0.0.1:9411
    enabled: true
  sleuth:
    sampler:
      probability: 1.0

테스트

디버그 모드로 실행

여기서 나오는 Trace ID cd753a9adc493db0
http://127.0.0.1:9411에서 검색 검색결과에서 자세한 정보를 확인할 수 있다.서비스 호출 순서도 확인할 수 있다.

  • Find a trace로 서비스 네임별 등 검색 가능
  • Dependencies로 의존구성 확인가능
  • 오류는 붉은색으로 나타난다
profile
개발자로써 성장하는 방법

0개의 댓글