FeignClient와 Ribbon 동작 원리
- 서비스 이름:
@FeignClient(name = "my-service")어노테이션은 Eureka에 등록된 서비스 이름을 참조- 서비스 인스턴스 조회: Eureka 서버에서
my-service라는 이름으로 등록된 서비스 인스턴스 목록을 조회- 로드 밸런싱: 조회된 서비스 인스턴스 목록 중 하나를 선택하여 요청을 보냅니다. 이는 기본적으로 Ribbon을 사용하여 로드 밸런싱을 수행
- 요청 분배: 여러 서비스 인스턴스가 있을 경우, Round Robin 또는 다른 설정된 로드 밸런싱 알고리즘을 사용하여 요청을 분배
- Order 서비스 실행: Order 서비스가 실행되면 Eureka 서버에서 Product 서비스 인스턴스 목록을 가져옵니다.
- Product 서비스 호출: Order 서비스에서 Product 서비스의 정보를 가져오기 위해 FeignClient를 사용하여 호출합니다.
- Ribbon을 통한 로드 밸런싱: FeignClient는 Ribbon을 통해 3개의 Product 인스턴스 중 하나를 선택하여 호출합니다. 이 과정에서 Round Robin 알고리즘을 사용하여 요청을 순차적으로 분배합니다.
- 응답 처리: 선택된 Product 인스턴스에서 응답을 받아 Order 서비스에 반환하고, 최종적으로 클라이언트에 응답을 전달합니다.
dependencies {
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'
implementation 'org.springframework.cloud:spring-cloud-starter-openfeign'
}
spring:
application:
name: product-service / order-service
server:
port: 19092
eureka:
client:
service-url:
defaultZone: http://localhost:19090/eureka/
@SpringBootApplication
@EnableFeignClients
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
}
}
@RestController
@RequiredArgsConstructor
public class OrderController {
private final OrderService orderService;
@GetMapping("/order/{orderId}")
public String getOrder(@PathVariable String orderId) {
return orderService.getOrder(orderId);
}
}
@FeignClient(name = "product-service")
public interface ProductClient {
@GetMapping("/product/{id}")
String getProduct(@PathVariable("id") String id);
}
@Service
@RequiredArgsConstructor
public class OrderService {
private final ProductClient productClient;
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...";
}
}
}
@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 {
@Value("${server.port}") // 애플리케이션이 실행 중인 포트를 주입받습니다.
private String serverPort;
@GetMapping("/product/{id}")
public String getProduct(@PathVariable String id) {
return "Product " + id + " info!!!!! From port : " + serverPort ;
}
}
