Hystrix
- Hystrix는 Netflix에서 공개한 대부분의 OSS에서 범용적으로 사용되는 오픈소스 라이브러리이다.
Hystrix는 다음과 같은 특징을 따른다.
- 분산환경을 위한 Latencey and Fault Tolerance 시스템
- 복잡한 분산 시스템에서 cascading failure를 멈춤
- 실패에 대해 빠르고 급격한 회복
- gracefully degrade와 fallback
- 거의 실시간으로 모니터링, 경고, 작동 제어가 가능하다.
Cascade Failure - 서비스간 장애 전파
대부분의 마이크로 서비스 아키텍쳐로 설계된 시스템에서 서비스 컴포넌트는 무수히 많이 존재하며, 서비스와 서비스 혹은 서비스와 게이트웨이 등 컴포넌트 별 호출은 일반적으로 REST-end-point를 가지기 때문에 Http 통신을 통해 서비스를 호출한다.
그런데 만일 어떤 서비스 컴포넌트나 Database, 아니면 시스템이 다운 됐을 경우 의존적으로 연결된 각 서비스는 Cascade Failure(계단식 오류, 연속적 오류)를 맞이하게 된다.
출처: https://subscription.packtpub.com/book/application_development/9781788624398/8/ch08lvl1sec60/when-the-services-fail-hello-hystrix
그림을 보면 쉽게 이해 할 수 있는데 장애가 발생한 Y서비스에, A서비스와 연결된 end-point를 comsumer가 호출할 경우 ex) /Service-Y/Service-A, A서비스와 M서비스 또한 잠재적으로 장애가 연속적으로 발생할 가능성이 높다.
이와 같은 문제를 Circuit Breaker Pattern을 통해 도움을 받을 수 있다.
Circuit Breaker Pattern
Hystrix는 Circuit breaker 패턴을 자바 기반으로 오픈소스화한 라이브러리이다.
출처: https://amandeepbatra.wordpress.com/2015/01/05/what-is-circuit-breaker-design-pattern/
- 만일 서비스가 정상적인 상황이라면, Client Request는 Remote Service를 호출하도록 by-pass한다.
- Database의 서비스가 장애가 발생했다면, 복구 될 때까지 Fallback 메세지와 함께 5xx response를 반환할 수 있다.
Hystrix Flow Chart
flow 차트는 위와 같은데, 아래의 코드를 통해 비교해보자
spring-cloud-starter-netflix-hystrix는 annotation 기반으로 간단하게 구성할 수 있다. Getting_Started
아래 코드는 spring-cloud-starter-netflix-hystrix가 아닌 webflux와 hystrix-javanica library를 추가해 각 단계별에 대해 분석하였다.
dependencies {
compile('com.netflix.hystrix:hystrix-javanica:1.5.10')compile('org.springframework.boot:spring-boot-starter-webflux')
}
1. HystrixCommand나 HystrixObservableCommand Object를 생성한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | static class MessageCacheGetCommand extends HystrixObservableCommand<Object> { @Autowired private final StatefulRedisConnection<String, String> redisConnection; private String id; private static Setter setter = Setter .withGroupKey(HystrixCommandGroupKey.Factory.asKey(MessageCacheGetCommand.class.getSimpleName())) .andCommandKey(HystrixCommandKey.Factory.asKey(MessageCacheGetCommand.class.getSimpleName())) .andCommandPropertiesDefaults( HystrixCommandProperties.Setter() .withExecutionIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrategy.SEMAPHORE) // semaphore strategy .withExecutionIsolationSemaphoreMaxConcurrentRequests(5) // failure 5 requsts, circuit on. .withExecutionTimeoutEnabled(true) .withExecutionTimeoutInMilliseconds(100) ); | cs |
2. execute(sync), queue(async), observe(hot observable), toObservable(cold observable) 중 선택하여 실행
1 2 3 4 | public Observable<Object> get(String id) { return new MessageCacheGetCommand(redisConnection, id).toObservable(); } | cs |
3. 캐쉬 응답이 있다면, Response를 수행한다.
4. Circuit이 Open되어 있으면 8) 단계로 넘어 간다.
1 2 3 4 5 | if (HystrixCircuitBreaker.Factory.getInstance(HystrixCommandKey.Factory.asKey(MessageCacheGetCommand.class.getSimpleName())).allowRequest()) { redisConnection.sync().setex(id, expireTimeSeconds, value); } else { log.info("Cache update canceled, Circuit breaker opened!"); } | cs |
5. Thread Pool/Queue/Semaphore가 Full이면 8)로 넘어간다.
6. HystrixObservableCommand.construct() 또는 HystrixCommand.run()을 수행한다. 수행 중 실패하거나 Timeout이 초과되면 8) 단계로 아니면 9) 종료 단계로 간다.
1 2 3 4 5 6 7 8 9 10 11 | @Override protected Observable<Object> construct() { return redisConnection.reactive() .get(id) .defaultIfEmpty(null) .map(value -> { return value; }); } | cs |
7. Circuit Health를 계산한다. Hystrix는 성공, 실패, Rejection 또는 Timeout 등의 정보를 Circuit Breaker에게 제공한다. Circuit Breaker는 이를 기반으로 Circuit을 열고 닫는다.
8. Fallback은 각 단계에서 실패, Timeout, Rejection 등이 발생할 때, 명시적인 핸들링을 할 수 있게하고 적절한 Response를 리턴할 수 있게한다.
1 2 3 4 | @Override protected Observable<Object> resumeWithFallback() { return Observable.empty(); } | cs |
9. 성공적으로 Response를 반환한다.
출처
https://github.com/Netflix/Hystrix/wiki/How-it-Works
https://medium.com/@goinhacker/hystrix-500452f4fae2
https://bcho.tistory.com/1247
https://supawer0728.github.io/2018/03/11/Spring-Cloud-Hystrix/
'Framework > Spring ' 카테고리의 다른 글
Spring AOP (1) (0) | 2019.08.02 |
---|---|
Spring Cloud Netflix (3) - zuul (0) | 2019.06.06 |
Spring Cloud Netflix (1) - OverView (0) | 2019.02.10 |
Spring Websocket (Handler, STOMP, Reactive Websocket) (6) | 2019.02.10 |