지난번 구성했던 POST 예제에 Hystrix를 적용하여 Resilience한 시스템을 구성해 봄
1. Hystrix?
MSA에서 분산된 서비스간 통신이 원할하지 않을 경우에 대비해 Netflix가 만든 Fault Tolerance Library
2. Background
Monolithic한 구조에서는 모듈사이의 메서드 호출이 실패하는 것을 고려하지 않음 ->시스템 자체가 죽지 않는 이상 그럴일이 없음
MSA에서 서로다른 서비스의 API 호출 시, 다양한 이유로 실패할 수 있는 가능성이 있음
API서버가 죽으면 Client 서버 역시 해당 서비스에 대해 장애가 생김 -> 장애가 전파됨
장애 전파를 막기 위해 API 호출 실패 시 대안을 적용해주어야 함
Hystrix를 활용하여 위 문제를 해결할 수 있다.
3. 예제
3-1. Dependency
<!--TIP
parent는 하나만 쓸 수 있다.
그렇기 때문에 groupId가 다른 cloud는 dependencyManagement로 의존성을 주입해주어야 한다.
reference : https://spring.io/projects/spring-cloud
-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
3-2. Ribbon Client(WebMain)
@EnableHystrix // Hystrix를 명시적으로 사용하기 위한 annotation
@SpringBootApplication
public class WebMainApplication {
public static void main(String[] args) {
SpringApplication.run(WebMainApplication.class, args);
}
}
/*
* Hystrix는 기본적으로 @Component / @Service를 찾고
* 그 안에 있는 @HystrixCommand를 찾아 동작한다.
*/
@Service("empInfoService")
public class EmpInfoService {
private static final Logger logger = LoggerFactory.getLogger(EmpInfoService.class);
private WebClient webClient = WebClient.builder()
.baseUrl("http://localhost:7077")
.build();
/* annotaion을 통해 CircuitBreaker 기능 활성화
* 만약 Circuit이 Open이 될 경우 fallback method 수행
* default timeout : 1 sec
* HystrixProperty : https://github.com/Netflix/Hystrix/wiki/Configuration
*/
@HystrixCommand(commandKey = "info", fallbackMethod = "getEmpInfoFallback",
commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "3000"), // set timeout value 3 sec
@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "10"), // error 비율이 10% 이상 발생하면 Circuit open
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "2") // 2회 이상 호출되면 통계 시작
})
public EmpInfo getEmpInfo() {
EmpInfo bodyEmpInfo = new EmpInfo();
bodyEmpInfo.setId(777);
bodyEmpInfo.setDomain("Jackpot");
return webClient.post() // POST method
.uri("/api/getUserInfo") // baseUrl 이후 uri
.bodyValue(bodyEmpInfo) // set body value
.retrieve() // client message 전송
.bodyToMono(EmpInfo.class) // body type : EmpInfo
.block(); // await
}
// fallback method, Communication 실패시 수행되는 method
private EmpInfo getEmpInfoFallback(Throwable t) {
logger.info(t.getMessage());
EmpInfo tmp = new EmpInfo();
tmp.setId(0);
tmp.setDomain("fallback123");
return tmp;
}
}
Reference
1. 기본기를 쌓는 정아마추어 코딩블로그Springboot hystrix 사용기 (hystrix로 마이크로 서비스 간의 서비스 호출 실패를 방지해보자), 정아마추어, 2019. 4. 16, https://jeong-pro.tistory.com/183
2. 11번가 Spring Cloud 기반 MSA로의 전환, Spring Camp, 윤용성, 2018. 5. 27, https://www.slideshare.net/balladofgale/spring-camp-2018-11-spring-cloud-msa-1
'MSA > Spring' 카테고리의 다른 글
[Spring Cloud] Ribbon을 활용한 Client Side Loadbalancing (0) | 2020.02.27 |
---|---|
[Spring Boot]WebClient를 이용한 POST 통신 (1) | 2020.02.26 |
[Spring Boot] 개발환경 세팅(visual studio code ver.) (0) | 2020.02.26 |