implementation 'org.springframework.cloud:spring-cloud-starter-circuitbreaker-resilience4j'
// 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;
}
...
}
// 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로 방지했다면 이제 분산 추적을 통해 어느 서비스끼리 통신하다 실패하였는지 추적을 해보자.
https://zipkin.io/pages/quickstart 에서
implementation 'org.springframework.cloud:spring-cloud-starter-sleuth'
implementation 'org.springframework.cloud:spring-cloud-starter-zipkin:2.2.3.RELEASE'
// 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
에서 검색 검색결과에서 자세한 정보를 확인할 수 있다.
서비스 호출 순서도 확인할 수 있다.