로드 밸런싱
네트워크 트래픽을 여러 서버로 분산시켜 서버의 부하를 줄이고, 시스템의 성능과 가용성을 높이는 기술이다.
서버 간 트래픽을 고르게 분배하여 특정 서버에 부하가 집중되는 것을 방지한다.
클라이언트 사이드 로드 밸런싱과 서버 사이드 로드 밸런싱이 있다.
클라이언트 사이드 로드 밸런싱
클라이언트가 직접 여러 서버 중 하나를 선택하여 요청을 보내는 방식이다.
서버의 목록을 가지고 있으며, 이를 바탕으로 로드 밸런싱을 수행한다.
FeignClient
Spring Cloud 에서 제공하는 HTTP 클라이언트로, 선언적으로 RESTful 웹 서비스를 호출할 수 있다.
Eureka와 같은 서비스 디스커버리와 연동하여 동적으로 서비스 인스턴스를 조회하고 로드 밸런싱을 수행한다.
FeignClient 주요 특징
선언적 HTTP 클라이언트 : 인터페이스와 어노테이션을 사용하여 REST API를 호출할 수 있다.
Eureka 연동 : Eureka와 통합하여 서비스 인스턴스 목록을 동적으로 조회하고 로드 밸런싱을 수행한다.
자동 로드 밸런싱 : Ribbon이 통합되어 있어 자동으로 로드 밸런싱을 수행한다.
Ribbon
넷플릭스가 개발한 클라이언트 사이드 로드 밸런서로, 마이크로서비스 아키텍처에서 서비스 인스턴스 간의 부하를 분산한다.
다양한 로드 밸런싱 알고리즘을 지원하며, Eureka와 같은 서비스 디스커버리와 연동하여 사용한다.
Ribbon 주요 특징
서버 리스트 제공자 : Eureka 등으로부터 서비스 인스턴스 리스트를 제공받아 로드 밸런싱에 사용한다.
로드 밸런싱 알고리즘 : 라운드 로빈, 가중치 기반 등 다양한 로드 밸런싱 알고리즘을 지원한다
Failover : 요청 실패 시 다른 인스턴스로 자동 전환한다.
로드 밸런싱 기술 사용
"주문" -> "상품" 은 주문하려는 상품 목록을 불러오는 과정을 표현한것이고,
주문을 생성하기 전에 어떤 상품들을 포함할지 조회하는 과정입니다.
" 사용자가 주문을 생성할 때, 주문 서비스는 상품 서비스로부터 선택된 상품들의 정보를 조회한다 "

위 사진을 보면 상품 서비스를 조회를 하려고 할 때 서비스 규모가 커지게 되자 서버를 추가 증설 하였고,
여기서 FeignClient 를 사용하면 라운드 로빈 알고리즘으로 각 19091, 19092, 19093 에 번갈아 가면서 요청을 하게 됩니다.
라운드 로빈
각 서버에 순차적으로 요청을 분배하는 방식입니다. 간단하고 공평하게 트래픽을 분산합니다.
FeignClient와 Ribbon 의 동작 원리
서비스 이름 : @FeignClient(name ="my-service") 어노테이션으로 Eureka 에 등록된 서비스 이름을 참조합니다.
서비스 인스턴스 조회 : Eureka 서버에서 my-service 라는 이름으로 등록된 서비스 인스턴스 목록을 조회합니다.
로드 밸런싱 : 조회된 서비스 인스턴스 목록 중 하나를 선택하여 요청을 보냅니다. 이는 기본적으로 Ribbon을 사용하여 로드 밸런싱을 수행합니다.
요청 분배 : 여러 서비스 인스턴스가 있을 경우, Round Robin 또는 다른 설정된 로드 밸런싱 알고리즘을 사용하여 요청을 분배합니다.
코드
product main
@SpringBootApplication
@EnableFeignClients
public class ProductApplication {
public static void main(String[] args) {
SpringApplication.run(ProductApplication.class, args);
}
}
product controller
@RestController
public class ProductController {
@Value("${server.port}")
private String serverPort;
@GetMapping("/product/{id}")
public String getProduct(
@PathVariable("id") String id
) {
return "Product : " + id + "info!! [ From port : " + serverPort + " ]";
}
}
order main
@SpringBootApplication
@EnableFeignClients
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
}
}
order productclient
@FeignClient(name = "product-service")
public interface ProductClient {
@GetMapping("/product/{id}")
String getProduct(@PathVariable String id);
}
order service
@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;
} else {
return "Not exist order...";
}
}
}
order controller
@RestController
@RequiredArgsConstructor
public class OrderController {
private final OrderService orderService;
@GetMapping("/order/{orderId}")
public String getOrder(
@PathVariable("orderId") String orderId
) {
return orderService.getOrder(orderId);
}
}
정리
order 프로젝트에 ProductClient 인터페이스를 생성해서 메서드를 정의한 이유에서 조금 더 깊게 공부해야 겠다는 생각이 들었다.
기존 모놀리식 방식으로 구현을 하게 되면 하나의 프로젝트 안에 모든 도메인이 있어서 DB에 있는 정보를 가져다 쓰기에 어렵지 않았다.
그러나, MSA 방식으로 개발을 하게 된다면 각 도메인마다 분리가 되어 있어 DB에 접근하여 데이터를 가지고 오기가 쉽지 않을거같다.
인터페이스를 만든 이유는 Order 서비스가 Product 서비스와 통신하기 위해서이다.
MSA에서는 각 서비스가 독립되어 있기 때문에 Order 는 Product의 DB나 코드에 직접 접근할수가 없다.
따라서 네트워크 통신, API호출을 통해서만 데이터를 가지고 올 수 있는데 그 역할을 담당하는 것이 바로 FeignClient 인터페이스이다.
'BACKEND & SERVER > Spring Boot MSA' 카테고리의 다른 글
| [Spring Boot] DTO에 Serializable을 사용하는 이유 (0) | 2025.10.30 |
|---|---|
| [Spring Boot] Spring Cloud GateWay & Filter (0) | 2025.10.27 |
| [Spring Boot] Resilience4j | 서킷브레이커 (0) | 2025.10.27 |
| [Spring Boot] RestClient vs FeignClient (0) | 2025.10.24 |
| [Spring Boot] Eureka | 서비스 디스커버리 (0) | 2025.10.24 |
