로드 밸런서로, 마이크로서비스 아키텍처에서 서비스 인스턴스 간의 부하를 분산build.gradle 파일 예시:dependencies {
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'
implementation 'org.springframework.cloud:spring-cloud-starter-openfeign'
}@SpringBootApplication
@EnableFeignClients // 어노테이션 추가
public class MyServiceApplication {
public static void main(String[] args) {
SpringApplication.run(MyServiceApplication.class, args);
}
}import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
@FeignClient(name = "my-service") // 호출하고자 하는 host
public interface MyServiceClient {
// 내부 메소드 작성하여 api 서비스 호출
@GetMapping("/endpoint")
String getResponse(@RequestParam(name = "param") String param);
}application.yml 파일 설정 예시:eureka:
client:
service-url:
defaultZone: http://localhost:8761/eurekamy-service:
ribbon:
eureka:
enabled: true #ribbon 활성화@FeignClient(name = "my-service") 어노테이션은 Eureka에 등록된 서비스 이름을 참조 (properties 파일의 name)my-service라는 이름으로 등록된 서비스 인스턴스 목록을 조회Order 서비스는 Product 서비스를 호출하여 상품 정보를 가져옵니다. 이 과정에서 어떻게 동작하는지 설명하겠습니다.
Order 서비스 인스턴스: 1개
Product 서비스 인스턴스: 3개
FeignClient를 사용하여 호출합니다.RESTful 웹 서비스를 호출
예시 코드:
http://my-service/endpoint?param=... 을 호출함
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
@FeignClient(name = "my-service")
public interface MyServiceClient {
@GetMapping("/endpoint")
// 요청 정보, 리턴 값 아래에 명시
String getResponse(@RequestParam(name = "param") String param);
}
Controller에서 FeignClient를 사용하여 다른 서비스 호출을 수행
예시 코드:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class MyController {
@Autowired
private MyServiceClient myServiceClient;
@GetMapping("/call-service")
public String callService(@RequestParam String param) {
return myServiceClient.getResponse(param);
// 위의 인터페이스에서 받아온 응답을 보냄
}
}
9분 이후

유레카 서버 하나에 order 인스턴스 1개와 같은 기능의 포트만 다른 product 인스턴스 3개를 연결합니다. (총 4개의 클라이언트 어플리케이션 생성)
상품을 요청(http://localhost:19091/order/1) 하면 응답하는 인스턴스의 포트를 받아서 노출합니다.
이를 통해 라운드로빈으로 로드밸런싱 (돌아가면서 product 호출)이 되는것을 확인합니다.
Product는 요청이 오면 아래의 문자열을 반환합니다.
”Product {productId} info!!!! From port : ${serverPort}”
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableFeignClients
public class ProductApplication {
public static void main(String[] args) {
SpringApplication.run(ProductApplication.class, args);
}
}
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ProductController {
// application.properties에서 가져옴
@Value("${server.port}") // 애플리케이션이 실행 중인 포트를 주입받습니다.
private String serverPort;
@GetMapping("/product/{id}")
public String getProduct(@PathVariable String id) {
return "Product " + id + " info!!!!! From port : " + serverPort ;
}
}
spring:
application:
name: product-service
server:
port: 19092
eureka:
client:
service-url:
defaultZone: http://localhost:19090/eureka/
19092,19093,19094 포트에 같은 애플리케이션 실행하기
1) 인텔리제이의 상단 메뉴에서 실행 > 구성 편집으로 들어갑니다.
2) ProductApplication을 복제하여 여러개 생성
3) ProductApplication 의 이름을 ProdcutApplication:19092로 변경합니다.
4) 옵션수정을 클릭하여 VM옵션 추가 > -Dserver.port=19093 을 입력
localhost:포트/product/아이디
입력하면 해당 포트에 해당하는 app이 실행된다.
Order는 요청이 오면 product를 호출하여 상품의 정보를 가져옵니다. 그리고 아래의 문자열을 반환합니다.
”Your order {orderId} product info => ${프로덕트에서 받은 문자열}”
주문은 주문아이디가 1인 주문만 있다고 가정하겠습니다.
1 주문은 112번 상품을 호출한다고 가정합니다.
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableFeignClients
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
}
}
import org.springframework.web.bind.annotation.RestController;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@RestController
@RequiredArgsConstructor
public class OrderController {
private final OrderService orderService;
// end-point 에서 입력 받아온 orderId에 해당하는
@GetMapping("/order/{orderId}")
public String getOrder(@PathVariable String orderId) {
return orderService.getOrder(orderId);
}
}
Product 인스턴스와 연결
```java
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
// 받아올 서비스의 이름을 Eureka에서 찾아와서 연결함
@FeignClient(name = "product-service")
public interface ProductClient {
// OrderService에서 호출하게 된다 //product 어플리케이션의 Controller의 getProduct를 호출한다``` import org.springframework.stereotype.Service;
import lombok.RequiredArgsConstructor;
@Service
@RequiredArgsConstructor
public class OrderService {
private final ProductClient productClient;
//product 어플리케이션의 Controller의 getProduct를 호출한다
public String getProductInfo(String productId) {
return productClient.getProduct(productId);
}
public String getOrder(String orderId) {
if(orderId.equals("1") ){
String productId = "2";
String productInfo = getProductInfo(productId);
return "Your order is " + orderId + " and " + productInfo;
}
return "Not exist order...";
}
}
spring:
application:
name: order-service
server:
port: 19091
eureka:
client:
service-url:
defaultZone: http://localhost:19090/eureka/
실행 순서
OrderController.getOrder > orderService.getOrder(orderId) > orderService.getOrder 내에서 getProductInfo > getProductInfo에서는 FeignClient의 productClient를 통해 product app 호출 / productClient 마다 포트가 있어서 실행 시 마다 어떤 포트에서 실행되는지 확인 가능
