로드 밸런싱이란?
로드 밸런싱은 네트워크 트래픽을 여러 서버로 분산시켜 서버의 부하를 줄이고, 시스템의 성능을 높이는 기술이다.
서버 간 트래픽을 고르게 분배하여 특정 서버에 부하가 집중되는 것을 방지한다.
클라이언트 사이드 로드 밸런싱
직접 여러 서버 중 하나를 선택하여 요청을 보내는 방식이다. 클라이언트는 서버의 목록을 가지고 있으며, 이를 바탕으로 로드 밸런싱을 수행한다.
FeignClient 란?
Spring Cloud에서 제공하는 HTTP 클라이언트이다. RESTful 웹 서비스를 호출할 수 있다.
Eureka와 같은 서비스 디스커버리와 연동하여 동적으로 서비스 인스턴스를 조회하고 로드 밸런싱을 수행한다.
Ribbon 이란?
넷플릭스가 개발한 클라이언트 사이드 로드 밸런서로, MSA에서 서비스 인스턴스 간의 부하를 분산한다.
마찬가지로 Eureka와 같은 서비스 디스커버리와 연동하여 사용한다.
로드 밸런싱 알고리즘 종류
1) 라운드 로빈
각 서버에 순차적으로 요청을 분배하는 방식이다. 좀 더 자세히 알아보자면 선입 선처리 스케줄링 + 타임 슬라이스를 사용한다.
타임 슬라이스란? 각 프로세스가 CPU를 사용할 수 있는 정해진 시간이다.
즉, 라운드 로빈 스케줄링은 선입 선처리 스케줄링을 하며 정해진 타임 슬라이스만큼의 시간 동안 돌아가며 CPU를 사용하는 선점형 스케줄링이다.
2) 가중치 기반 로드 밸런싱
각 서버에 가중치를 부여하고, 가중치에 비례하여 요청을 분배하는 방식이다.
3) 기타 알고리즘
최소 연결 : 현재 연결된 클라이언트 수가 가장 적은 서버로 요청을 보내는 방식이다.
응답 시간 기반 : 서버의 응답 시간을 기준으로 가장 빠른 서버로 요청을 보내는 방식이다.
FeignClient 와 Eureka 연동
Eureka와 FeignClient를 함께 사용하면 동적으로 서비스 인스턴스를 조회하여 로드 밸런싱을 수행한다.
Order 서비스 인스턴스 1개와 Product 서비스 인스턴스 3개 실습 시나리오
유레카 서버 하나에 Order 인스턴스 1개와 같은 기능에 포트만 다른 Product 인스턴스 3개를 연결한다.
상품을 요청(http://localhost:19091/order/1) 하면 응답하는 인스턴스의 포트를 받아서 노출한다.
이를 통해 라운드 로빈으로 로드밸런싱이 되는 것을 확인한다.
1) 먼저 product 서비스 인스턴스 3개를 등록한다.
@SpringBootApplication
@EnableFeignClients
public class ProductApplication {
public static void main(String[] args) {
SpringApplication.run(ProductApplication.class, args);
}
}
@RestController
public class ProductController {
@Value("${server.port}")
private String serverPort;
@GetMapping("/product/{id}")
public String getProduct(@PathVariable("id") String id) {
// 해당 어플리케이션의 서버 port 리턴
return "Product "+id+" info!!!! From port : " + serverPort;
}
}
각기 다른 product 19092, 19093, 19094 포트를 등록하고 띄워준다.
http://localhost:1909(2~4)/product/1로 접근하면 각각 다른 포트의 product 페이지가 나온다.
Eureka 중앙 서버로 들어가면 이렇게 product 포트 3개가 떠 있는 걸 확인할 수 있다.
2) order 서비스 인스턴스 1개를 등록한다.
FeignClient 인터페이스를 작성해 원하는 서비스 호출을 수행한다. name에 원하는 서비스 이름을 적어주면 이 name 식별자를 가지고 유레카 서버에서 서비스를 찾는다.
@FeignClient(name = "product-service")
public interface ProductClient {
@GetMapping("/product/{id}")
String getProduct(@PathVariable("id") String id);
}
order 컨트롤러에 원하는 작업을 등록한다.
@RestController
@RequiredArgsConstructor
public class OrderController {
final OrderService orderService;
@GetMapping("/order/{orderId}")
public String getOrder(@PathVariable("orderId") String orderId) {
return orderService.getOrder(orderId);
}
}
order 서비스에서 product 호출의 결과값을 받아오고, getOrder 로직에서 어떤 product port에 접근했는지 확인하는 서비스 코드를 작성한다.
@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...";
}
}
위 사진들처럼 localhost:19091/order/1에 접근할 때마다 product의 포트가 1909(2~4)로 로드 밸런싱되며 변경되는것을 확인할 수 있다.
결과적으로, /order/1 요청을 여러 번 보낼 때 마다 응답에서 product 포트 번호가 순차적으로 로드 밸런싱 되는 것을 확인할 수 있다.
'Backend > MSA' 카테고리의 다른 글
241125 보안 구성 (OAuth2 + JWT) 실습 TIL (1) | 2024.11.25 |
---|---|
241122 API 게이트웨이 실습 TIL (0) | 2024.11.22 |
241121 서킷 브레이커 (Resilience4j) 실습 TIL (0) | 2024.11.21 |
241120 서비스 디스커버리 (Eureka) 실습 TIL (0) | 2024.11.21 |
241120 MSA에 대해서 알아보자 TIL (1) | 2024.11.20 |