해당 포스팅은 Spring Cloud로 개발하는 마이크로서비스 애플리케이션(MSA)
강의를 듣고 정리한 글입니다. 실습 환경을 따라하시려면 이전 글에 나온 실습을 진행하시고 해당 포스팅을 읽는 것을 추천드립니다.
마이크로 서비스간 통신하는 방법은 크게 두가지가 있습니다.
1. RestTemplate 이용
2. FeignClient
RestTemplate
를 이용하는 방법과 FeignClient
를 이용하는 방법 두 가지를 해보자.
@Bean
@LoadBalanced
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
user-service
에서 order-service
에 있는 엔드포인트 {userId}/orders 를 호출하고 싶다. @GetMapping("{userId}/orders")
public ResponseEntity<List<ResponseOrder>> getOrder(@PathVariable("userId") String userId) throws Exception {
log.info("Before retrieve orders data");
Iterable<OrderEntity> orderList = orderService.getOrdersByUserId(userId);
List<ResponseOrder> result = new ArrayList<>();
orderList.forEach(v->{
result.add(new ModelMapper().map(v, ResponseOrder.class));
});
// try {
// Thread.sleep(1000);
// throw new Exception("장애 발생");
// } catch (InterruptedException exception) {
// log.warn(exception.getMessage());
// }
log.info("Add retrieve orders data");
return ResponseEntity.status(HttpStatus.OK).body(result);
}
호출하고자 하는 API 스펙에 맞게 user-service
에서 RestTemplate을 이용해보자
exchange메서드
new ParameterizedTypeReference
에 알맞은 DTO를 정의하여 받아주면 정상적으로 다른 MSA의 API를 호출할 수 있다.요청을 보낼 user-service
의 API
@GetMapping("/users/{userId}")
private ResponseEntity<ResponseUser> getUser(@PathVariable String userId) {
UserDto userDto = userService.getUserByUserId(userId);
ResponseUser returnValue = new ModelMapper().map(userDto, ResponseUser.class);
return ResponseEntity.status(HttpStatus.OK).body(returnValue);
}
Postman을 통한 테스트
메서드를 호출하는 것과
겉보기에 비슷하게 보일 수 있다.장점
단점
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
@EnableFeignClients
public class UserServiceApplication {
public static void main(String[] args) {
SpringApplication.run(UserServiceApplication.class, args);
}
}
@FeignClient(name="order-service")
public interface OrderServiceClient {
@GetMapping("/order-service/{userId}/orders")
List<ResponseOrder> getOrders(@PathVariable String userId);
}
@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);
//// List<ResponseOrder> orders = new ArrayList<>();
// /* Using as rest template */
// String orderUrl= String.format(env.getProperty("order_service.url"), userId);
// ResponseEntity<List<ResponseOrder>> orderListResponse = restTemplate.exchange(orderUrl, HttpMethod.GET, null, new ParameterizedTypeReference<List<ResponseOrder>>() {
// });
// List<ResponseOrder> ordersList = orderListResponse.getBody();
/*FeignClient 사용*/
/*Feign exception handling*/
List<ResponseOrder> ordersList = null;
try {
ordersList = orderServiceClient.getOrders(userId);
} catch (FeignException exception) {
log.error(exception.getMessage());
}
userDto.setOrders(ordersList);
return userDto;
}
이번 포스팅을 통해서 마이크로 서비스간 통신하는 2가지 방법을 배우고 정리해봤다. 2가지 방법중에 프로젝트에 적용할떄는 FeignClient를 적용할 것 같다. 가독성 측면에서 좋고 간단한 방식으로 이용할 수 있기 때문이다.