2019. 11. 14. 22:49ㆍSpring Micro Services/Service Discovery with Eureka
Spring Discovery Service with Netflix Eureka - Client
앞에 예제에서는 Eureka Server 를 만들어 보았다. 이제 실제적인 클라이언트 서비스를 만들어 보도록 하자. 앞에서 이미 필요한 프로젝트는 생성 하였기 때문에 각 서비스 별로 변경 된 부분에 대해서 살펴 보도록 하겠다.
프로젝트 전체 소스는 https://github.com/roopy1210/spring-msa-with-eureka 참고하여 주기 바랍니다.
Eureka Client - 주문서비스
주문서비스는 사용자가 http://localhost:7000/order URL을 통하여 접속한다. 이제 설정파일, 메인프로그램, Controller 순으로 살펴보도록 하자.
01. application.yml
server: port: 7000 spring: application: name: order-service datasource: hikari: connection-test-query: SELECT 1 minimum-idle: 1 maximum-pool-size: 5 driver-class-name: org.postgresql.Driver url: jdbc:postgresql://localhost:5432/postgres username: postgres password: admin!@34 jpa: database-platform: org.hibernate.dialect.PostgreSQLDialect show-sql: true properties: hibernate: format_sql: true temp.use_jdbc_metadata_defaults: false hibernate: naming: implicit-strategy: org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl eureka: instance: leaseRenewalIntervalInSeconds: 1 leaseExpirationDurationInSeconds: 2
02. OrderApplication
package com.roopy.services.order; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.context.annotation.Bean; import org.springframework.web.client.RestTemplate; @SpringBootApplication @EnableEurekaClient public class OrderApplication { public static void main(String[] args) { SpringApplication.run(OrderApplication.class, args); } @Bean @LoadBalanced public RestTemplate getRestTemplate() { return new RestTemplate(); } }
위의 소스에서 RestTemplate 소스와 비교해서 변경 된 부분은 ① @EnableEurekaClient ② @LoadBalanced 어노테이션이 추가 된것이다.
- @EnableEurekaClient : EurekaServer 에 서비스를 등록한다.
- @LoadBalanced : IP가 아닌 위의 설정파일에서 선언한 sping.application.name 으로 서비스간 통신을 할 수 있다.
package com.roopy.services.order.controller; import java.util.HashMap; import java.util.List; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpEntity; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; import com.roopy.services.order.domain.Order; import com.roopy.services.order.helper.IDGeneratorHelper; import com.roopy.services.order.service.IOrderService; @RestController public class OrderController { @Autowired private RestTemplate restTemplate; @Autowired private IOrderService orderService; @Autowired private IDGeneratorHelper idGenerator; @SuppressWarnings({ "rawtypes", "unchecked" }) @RequestMapping(value = "/order", method = RequestMethod.POST) public Order save(HttpServletRequest request, HttpServletResponse response, @RequestBody Order order) throws Exception { // 주문ID생성 String orderId = idGenerator.getOrderId(); // 주문ID설정 order.setOrderId(orderId); // 주문날짜설정 order.setOrderDtm(orderId.substring(1)); // 결제처리 HttpEntity<Order> ordRequest = new HttpEntity<>(order); ResponseEntity<List> pymentResponse = restTemplate.postForEntity("http://payment-service/payment", ordRequest, List.class); // 상품수량업데이트처리 ResponseEntity<List> productResponse = null; if (pymentResponse.getStatusCodeValue() == 200) { productResponse = restTemplate.postForEntity("http://product-service/products", ordRequest, List.class); } // 주문정보저장 if (pymentResponse.getStatusCodeValue() == 200 && productResponse.getStatusCodeValue() == 200) { /*결제처리와 상품정보 업데이트가 정상적으로 처리 된 경우 주문상태를 완료로 변경한다.*/ order.setOrderStatus("C"); order = orderService.save(order); order.setPayments(pymentResponse.getBody()); } return order; } @RequestMapping(value = "/order/{orderId}", method = RequestMethod.POST) public Order findOrder(HttpServletRequest request, HttpServletResponse response, @PathVariable String orderId, @RequestParam HashMap<String, String> param) throws Exception { return orderService.find(orderId); } }
위에서 설명한데로 서비스 호출 시 http://payment-service/payment, http://product-service/products IP가 아닌 서비스 이름으로 API 를 호출 하게 된다.
Eureka Client - 결제서비스
메인 프로그램 부문만 @EnableEurekaClient 어노테이션이 추가 되었다.
01. PaymentApplication
package com.roopy.services.payment; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; @SpringBootApplication @EnableEurekaClient public class PaymentApplication { public static void main(String[] args) { SpringApplication.run(PaymentApplication.class, args); } }
Eureka Client - 상품서비스
메인 프로그램 부문만 @EnableEurekaClient 어노테이션이 추가 되었다.
01. ProductApplication
package com.roopy.services.product; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; @SpringBootApplication @EnableEurekaClient public class ProductApplication { public static void main(String[] args) { SpringApplication.run(ProductApplication.class, args); } }
Eureka Server 서비스 등록 확인
다음과 같은 순서로 서비스를 실행한다.
1. Eureka Server 실행 - discovery-service
2. Eureka Client 실행 - order-service
3. Eureka Client 실행 - payment-service
4. Eureka Client 실행 - product-service
정상적으로 서비스가 실행되었으면 아래와 같이 서비스가 다 등록된 것을 확인 할 수 있다.
테스트
RestTemplate 주문서비스 구현 부분의 Postman 테스트와 동일하게 실행 하면 된다.
지금까지 Eureka Sever, Client에 대해 알아 보았다.
'Spring Micro Services > Service Discovery with Eureka' 카테고리의 다른 글
Spring Cloud: Discovery Service with Netflix Eureka - Server (0) | 2019.11.12 |
---|