2024. 12. 11. 14:06ㆍSpring Microservice
Spring Boot의 Client-Side Load Balancing
Client-Side Load Balancing은 서비스 소비자가 서비스 요청을 보내기 전에 직접 서비스 인스턴스 목록을 가져와 적절한 인스턴스를 선택하여 요청을 분배하는 방식입니다. 이 방식은 클라이언트가 로드 밸런싱 책임을 지며, Spring Boot에서는 주로 Spring Cloud LoadBalancer를 통해 구현됩니다.
클라이언트의 정의
위에서 설명한 클라이언트(Client)는 일반적으로 생각하는 웹 브라우저(웹 클라이언트)가 아닌, 애플리케이션 간 통신에서 다른 서비스를 호출하는 마이크로서비스나 애플리케이션을 의미합니다.
이 경우 클라이언트는 마이크로서비스 환경에서 다른 서비스를 호출하고 요청을 처리하는 서비스 소비자(Service Consumer)입니다. 예를 들어:
- 서비스 제공자 (Service Provider): 데이터를 제공하거나 특정 기능을 실행하는 서비스.
- 서비스 소비자 (Service Consumer, 클라이언트): 다른 서비스로부터 데이터를 요청하거나 기능을 호출하는 서비스.
즉, 서비스 디스커버리와 로드 밸런싱이 필요한 클라이언트는 백엔드 서비스나 비즈니스 로직을 실행하는 애플리케이션입니다.
예제 시나리오
- 웹 브라우저:
- 사용자는 웹 브라우저에서 특정 URL로 요청을 보냅니다.
- 이 요청은 클라이언트가 아닌, 백엔드 애플리케이션(예: API Gateway 또는 Spring Boot 애플리케이션)으로 전달됩니다.
- 클라이언트 (Service Consumer):
- 백엔드 애플리케이션(예: Spring Boot 애플리케이션)은 로드 밸런싱을 적용하여 다른 마이크로서비스로 요청을 보냅니다.
- 이 백엔드 애플리케이션이 바로 클라이언트입니다.
간단한 구조
[사용자] → [웹 브라우저] → [API Gateway 또는 Backend Service (클라이언트)] → [다른 서비스 (서비스 제공자)]
- 웹 브라우저: 사용자가 직접 상호작용하는 인터페이스.
- 클라이언트: 백엔드의 일부로 동작하며, 사용자의 요청을 처리하기 위해 다른 서비스를 호출.
클라이언트 예시
클라이언트 코드 (Service Consumer):
@RestController
public class ClientController {
private final RestTemplate restTemplate;
public ClientController(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
@GetMapping("/consume")
public String consumeService() {
// 다른 서비스 호출
String url = "http://SERVICE-NAME/api/resource";
return restTemplate.getForObject(url, String.class);
}
}
- 위의 코드에서
ClientController
는 클라이언트로 동작합니다. - 서비스 이름(SERVICE-NAME)을 사용하여 다른 서비스(서비스 제공자)로 요청을 보냅니다.
summary
- 웹 브라우저: 사용자 인터페이스로 사용되며, 로드 밸런싱과 관련이 없습니다.
- 클라이언트: 백엔드 애플리케이션 또는 마이크로서비스에서 다른 서비스를 호출하는 소비자입니다.
- 스프링 부트의 Client-Side Load Balancing은 마이크로서비스 간의 통신에서 작동하며, 웹 브라우저와는 직접적인 관련이 없습니다.
Client-Side Load Balancing의 작동 원리
- 서비스 디스커버리:
- 클라이언트는 Eureka, Consul, 또는 Kubernetes와 같은 서비스 레지스트리에서 서비스 인스턴스의 정보를 가져옵니다.
- 서비스 이름으로 요청하면, 해당 서비스의 모든 가용 인스턴스 목록을 반환받습니다.
- 로드 밸런싱:
- 클라이언트는 가용 인스턴스 목록에서 적절한 인스턴스를 선택합니다.
- 선택 기준은 Round Robin, Random, Weighted 등 다양한 전략이 사용됩니다.
- 요청 전달:
- 선택된 인스턴스에 요청을 보냅니다.
Spring Boot에서의 Client-Side Load Balancing 구현
Spring Boot는 이전에 Netflix Ribbon을 사용했지만, Spring Cloud 2020 릴리스 이후에는 Spring Cloud LoadBalancer가 디폴트 client side 로드 밸런싱 라이브러리로 사용됩니다.
Spring Cloud LoadBalancer의 주요 기능
- 다양한 로드 밸런싱 알고리즘 제공 (Round Robin, Random 등).
- Eureka, Consul, Kubernetes와의 통합.
- 커스터마이징 가능한 로드 밸런싱 전략.
Spring Boot 설정 및 구현 예시
1. 의존성 추가
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
2. Eureka 설정
application.yml
:
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
instance:
prefer-ip-address: true
3. RestTemplate 사용
Spring Boot에서 RestTemplate
를 클라이언트 사이드 로드 밸런싱과 함께 사용할 수 있습니다.
@Configuration
public class RestTemplateConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
@LoadBalanced
를 사용하면 RestTemplate이 서비스 이름(SERVICE-NAME
)을 IP 주소로 변환하고, 적절한 인스턴스를 선택합니다.
4. 서비스 호출
@RestController
public class ClientController {
private final RestTemplate restTemplate;
public ClientController(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
@GetMapping("/consume")
public String consumeService() {
// "SERVICE-NAME"은 Eureka에 등록된 서비스 이름입니다.
String url = "http://SERVICE-NAME/api/resource";
return restTemplate.getForObject(url, String.class);
}
}
로드 밸런싱 전략 커스터마이징
Spring Cloud LoadBalancer는 기본적으로 Round Robin 전략을 사용합니다. 하지만, 전략을 변경하거나 커스터마이징할 수도 있습니다.
1. 기본 전략 변경
Round Robin 대신 Random 전략으로 변경하려면 다음과 같이 설정합니다.
@Bean
ReactorLoadBalancer<ServiceInstance> randomLoadBalancer(Environment environment,
LoadBalancerClientFactory loadBalancerClientFactory) {
String serviceId = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
return new RandomLoadBalancer(loadBalancerClientFactory.getLazyProvider(serviceId, ServiceInstanceListSupplier.class), serviceId);
}
2. 커스터마이징 전략
특정 메타데이터를 기반으로 로드 밸런싱 전략을 구현할 수도 있습니다.
예: 서비스의 가중치 기반 선택
public class WeightedLoadBalancer extends RoundRobinLoadBalancer {
public WeightedLoadBalancer(ServiceInstanceListSupplier supplier, String serviceId) {
super(supplier, serviceId);
}
@Override
public Mono<Response<ServiceInstance>> choose(Request request) {
return super.choose(request).flatMap(instance -> {
// 가중치 기반 선택 로직 추가
return Mono.just(instance);
});
}
}
Spring Cloud Gateway와의 통합
Spring Cloud LoadBalancer는 RestTemplate뿐만 아니라 Spring Cloud Gateway와도 통합 가능합니다. 이는 서버 사이드 디스커버리와 함께 사용할 때 유용합니다.
spring:
cloud:
gateway:
discovery:
locator:
enabled: true
이 설정은 Gateway가 Eureka 서비스 레지스트리에서 서비스 목록을 조회하고, 클라이언트 요청을 적절한 서비스로 전달하도록 합니다.
Client-Side Load Balancing의 장점과 단점
장점
- 네트워크 최적화:
- 클라이언트가 서비스 인스턴스를 직접 선택하기 때문에 네트워크 지연 시간이 줄어듭니다.
- 유연성:
- 클라이언트가 로드 밸런싱 전략을 자유롭게 변경하거나 커스터마이징할 수 있습니다.
- 분산 처리:
- 로드 밸런싱 로직이 분산되어 서버 로드가 줄어듭니다.
단점
- 클라이언트 복잡성 증가:
- 클라이언트가 서비스 디스커버리와 로드 밸런싱 책임을 가지므로 코드가 복잡해질 수 있습니다.
- 캐싱 문제:
- 클라이언트는 서비스 인스턴스 목록을 캐싱해야 하므로, 레지스트리 정보가 변경될 경우 실시간 반영이 어려울 수 있습니다.
- 스케일링:
- 많은 클라이언트가 서비스 레지스트리에 직접 접근하면, 레지스트리의 부하가 증가할 수 있습니다.
Client-Side Load Balancing이 필요한 경우
- 마이크로서비스 환경: 서비스 인스턴스가 동적으로 추가/제거되는 환경에서 유용합니다.
- 고가용성 요구: 클라이언트가 다수의 서비스 인스턴스 중 하나를 선택해 요청을 분배하여 고가용성을 제공합니다.
- 클라이언트 제어: 클라이언트에서 직접 로드 밸런싱 전략을 설정하거나 수정해야 할 경우 적합합니다.
Spring Boot의 Client-Side Load Balancing은 마이크로서비스 환경에서 유연성과 확장성을 제공합니다. Spring Cloud LoadBalancer를 사용하여 Eureka와 같은 서비스 레지스트리와 통합하면, 복잡한 분산 시스템에서 서비스 간의 연결을 간단히 관리할 수 있습니다. 또한, 로드 밸런싱 전략을 커스터마이징함으로써 다양한 비즈니스 요구사항을 충족할 수 있습니다.
'Spring Microservice' 카테고리의 다른 글
서비스 디스커버리 클라이언트 Push/Pull (0) | 2024.12.11 |
---|---|
Gossip Protocol (0) | 2024.12.11 |
유레카 클라이언트 설정 (0) | 2024.12.11 |
Spring boot의 서비스 디스커버리 개념 (0) | 2024.12.11 |
클라우드 기반 서비스 디스커버리 에이전트 (0) | 2024.12.11 |