동기 요청 예시
첫번째
- Catalogs1 이라는 프로젝트가 있고, Customers1이라는 프로젝트가 있을 때
- Catalogs의 Controller에서 service를 호출하는데, service에서
RestTemplate
라이브러리를 주입하여getForObject
라는 대표 메서드를 통해 Customer1에 요청을 보냄.
응답 결과가 Customer1에서 나옴, Customer1의 return값을 호출한 Catalogs에 보내준다.- 서버는 둘다 돌려야되고 postman에서는
http://localhost:8081/catalogs/customerinfo/{id}
로 확인
서비스간 장애가 났을때 장애를 차단하는 방법
: Hystrix 사용해보기
-> advice와 비슷하다. getForObject를 호출하다가 문제가 생겼을 때 그 즉시 처리용 메서드(fallbackMethod)를 실행하라.
- 사용자에게 문제를 알릴것인가? 정확한 메시지를 알릴 수 있겠지만, 간단하게 정상응답을 못합니다라고 return값으로 가공해서 보냄
- 서비스역할을 하는 customer까지 가지 않고, endpoint역할을하는 catalog에서 보냄
Circuit Open
* 요청이 다음단계로 넘어가지 않고 미리 반환하는 작업
* 기본설정은
* 10초동안 20개이상의 @HystrixCommand메서드호출이 발생했을때,
* 50%이상의 호출에서 에러가 발생되면 자동 Circuit Open된다.
-> 회로차단 -> 이 경우 수가 발생하면 그때부턴 더 메서드 호출하러 안감.
-> 그즉시 fallback해버림
* Circuit Open되면 fallbackMethod로 처리
* 프로퍼티 : requestVolumeThreshold - @HystrixCommand메서드 호출건수(1)
* errorThresholdPercentage - 에러발생확률(50)
Catalog 의 서비스
1) 어노테이션
@Override
@HystrixCommand(fallbackMethod = "getCustomerDetailFallback"
//// ,commandProperties = {@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds", value="500") }
//// ,commandProperties = {@HystrixProperty(name="circuitBreaker.requestVolumeThreshold", value="1"),
//// @HystrixProperty(name="circuitBreaker.errorThresholdPercentage", value="50")}
//
)
2) yml 사용
hystrix:
command:
default: # command Key. use 'default' for global setting.
execution:
isolation:
thread:
timeoutInMilliseconds: 500
// 0.5초 내에 응답안오면 exception 보낼거야~
// 응답이 올 때 까지 기다리지 않고 이 시간이 지나면 바로 fallbackMethod 보냄
# metrics.rollingStats.timeInMilliseconds : 오류 감시 시간, 기본값 10초
# circuitBreaker.requestVolumeThreshold : 감시 시간 내 요청 수, 기본값 20
# circuitBreaker.errorThresholdPercentage : 요청 대비 오류율, 기본값 50
metrics: #1분(60000)동안 최소 2회 호출 이상, 50% 이상 실패면 circuit open
rollingStats:
timeInMilliseconds: 60000
circuitBreaker:
requestVolumeThreshold: 2
errorThresholdPercentage: 50
CustomerController
@RestController
@RequestMapping("/customers")
public class CustomerController {
int cnt=0;
@GetMapping("/{customerId}")
public String getCustomerDetail(@PathVariable String customerId) {
// 1) timeout test : 기본 timeout값은 1000 (1초)
long milli = 3*1000; // 3초가 지난 다음에 응답하라
try {
Thread.sleep(milli);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("request customerId :" + customerId);
return "[Customer id = " + customerId + " at " + System.currentTimeMillis() + "]";
//2) exception test
// throw new RuntimeException("I/O Exception");
//3)circuit open test
// System.out.println("처리횟수:" + (++cnt));
// throw new RuntimeException("I/O Exception");
}
↳ CustomerController에서 3초 지난다음에 응답하라고 했고, catalog에서는 0.5초만 기다린다고 해서 무조건 exception발생할것임.
1) timeOut : hystrixException보냄
2) 서킷브레이커가 오픈될 때 : RuntimeException을 발생시키면 internalServerError가 발생함 -> 사용자에게 던져주는 것이 아니라 고객 정보 조회가 지연된다는 fallback메서드로 가공돼서 보내짐
-> 클라이언트에 500번으로 그대로 노출하지 않고 endpoint로 지정해놓은 catalog에서 메시지를 가공해서 보내는것이다.
-> fallback메서드 안지정해놓으면 그 에러 그대로 노출함!