Github 소스코드
🔎 이런거 해볼 거에요.
- 두 개 MSA
User service와Order service는Eureka Service에 등록되어 있는 상태이고,Spring cloud gateway에 의해 라우팅된다. - User service에서 Order service로 주문정보를 얻어오기 위해 요청을 보내고자 한다.
- RestTemplate를 이용하는 방법과 FeignClient를 이용하는 방법 두 가지를 해보자.
RestTemplate
1. 가장 먼저 RestTemplate를 사용하기 위해 해당 모듈을 Bean으로 등록해주어야 한다.
- 간단한게 springboot의 main class에 Bean을 등록한다.
@Bean public RestTemplate getRestTemplate() { return new RestTemplate(); }2. 호출하고자 하는 service의 API를 확인해보자.
- 내부 동작이 아닌 주소 매핑정보와 리턴타입을 확인한다.
@GetMapping("/orders/{userId}") public ResponseEntity<List<ResponseOrder>> getOrderByOrderId(@PathVariable("userId") String userId) { List<OrderDto> findOrders = orderService.getOrderByUserId(userId); ModelMapper mapper = new ModelMapper(); mapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT); List<ResponseOrder> result = new ArrayList<>(); findOrders.forEach( o -> { result.add(mapper.map(o, ResponseOrder.class)); }); return ResponseEntity.status(HttpStatus.OK).body(result); } } - Order service가 API gateway service에 등록된 설정을 보자.
``` - id: order-service
uri: lb://ORDER-SERVICE
predicates:
Path=/order-service/**endpoint는 ```/orders/{userId}``` 이고 api gateway에 ```order-service```로 등록되어 있으니 호출해야 하는 API의 uri는 ``` http://127.0.0.1:8000/order-service/orders/{userId} ``` 가 된다.
3. User service의 service계층에서 RestTemplate을 통해 호출해보자.
- RestTemplate는 앞서 Bean으로 등록했으므로 주입받아 사용한다. (저는
@RequiredArgsConstructor+final로 받았어요.)private final RestTemplate restTemplate; - RestTemplate의 exchange메서드르 이용한다.
- exchange(url, HttpMethod, requestEntity, responseType)
- body는 없으므로
requestEntity는 null로 하고 응답받을 타입은ParameterizedTypeReference로 지정한다.
new ParameterizedTypeReference에 알맞은 DTO를 정의하여 받아주면 정상적으로 다른 MSA의 API를 호출할 수 있다.
String url = String.format("http://127.0.0.1:8000/order-service/orders/%s", userId);
ResponseEntity<List<ResponseOrder>> response = restTemplate.exchange(url, HttpMethod.GET, null,
new ParameterizedTypeReference<List<ResponseOrder>>() {
});
List<ResponseOrder> orders = response.getBody();
FeignClient
1. FeignClient를 위한 interface를 생성한다.
@FeignClient에는 호출하고자 하는 MSA이름을 지정한다.여기서 MSA의 이름은 Eureka server에 인스턴스로 등록시 사용된 이름이다.
이렇게 FeignClient로 설정해주면 마치 자신의 API인 것처럼 정의가 가능하다.
@GetMapping쪽을 보면 기존에 Controller에서 endpoint를 지정하는 것과 거의 동일한 것을 알 수 있다. 다만 세부 구현 내용은 필요로 하지 않는다.@FeignClient(name = "order-service") public interface OrderServiceFeignClient { @GetMapping("/order-service/orders/{userId}") List<ResponseOrder> getOrders(@PathVariable String userId);
}
#### 2. Service계층에서 정의한 FeignClient로 Order-Service를 호출해보자.
- 정의한 FeignClient을 주입받는다. 이전과 동일하게 ```@RequiredArgsConstructor``` + ```final```로 주입받는
다.
```java
private final OrderServiceFeignClient orderServiceFeignClient; - 주입받은 객체로 정의한 API를 호출한다.
- FeignClient에서 제공하는 에러처리 기법이 있어 이후 사용해 볼 것이다. 일단
try-catch문으로 예외를 처리한다. - RestTemplate보다는 FeignClient가 코드도 분리되고 훨씬 더 간결하여 좋다는 느낌이 든다.
List<ResponseOrder> orders = null;
try {
orders = orderServiceFeignClient.getOrders(userId);
} catch (FeignException e) {
log.error(e.getMessage());
}
3. FeignClient에서 ErrorDecoder를 이용한 예외처리
ErrorDecoder를 이용하여 예외를 모아 관리할 수 있다.ErrorDecoder를 구현하는 클래스를 생성하고 아래와 같은 리턴값, 매개변수를 갖는 decode 메서드를 오버라이딩한다.첫번째 매개변수인 method에는 FeignClient를 통해 호출한 함수의 이름을 포함한다. 때문에 에러 케이스마다 호출한 함수의 명에 따라 구분하여 처리가 가능하다.
리턴값은 임의대로 Exception객체를 적절하게 구성하여 리턴한다.
@Component public class FeignClientErrorDecoder implements ErrorDecoder { @Override public Exception decode(String method, Response response) { switch (response.status()) { case 404: if(method.contains("getOrders")) { return new ResponseStatusException(HttpStatus.valueOf(response.status()), "User's order is empty."); } break; default: return new Exception(response.reason()); } return null; } }ErrorDecoder를 구현하면try-catch없이 아래와 같이 깔끔하게 다른 MSA의 API를 호출할 수 있다.List<ResponseOrder> orders = orderServiceFeignClient.getOrders(userId);
'Spring Cloud' 카테고리의 다른 글
| 패스트캠퍼스 챌린지 30일차 - Spring Cloud 1 (0) | 2021.10.05 |
|---|---|
| 🌱 Spring Cloud - API Gateway Service (Load Balancing) 🌱 (0) | 2021.08.20 |
| 🌱 Spring Cloud - API Gateway Service (Routing) 🌱 (0) | 2021.08.20 |
| 🌱 Spring Cloud - Service Discovery (Netflix Eureka) 🌱 (0) | 2021.08.20 |