Spring Cloud Eureka 서비스 디스커버리 - 서비스 소비 구현 전략

Eureka 서비스 레지스트리 구축 실습

본 글은 Spring Cloud Eureka를 활용한 서비스 디스커버리와 소비 과정을 단계별로 설명합니다. 참고 자료는 Spring Cloud 공식 문서 및 관련 예제를 기반으로 합니다.

1. 서비스 프로바이더 등록

목표: 서비스 제공 애플리케이션을 생성하고 Eureka 레지스트리에 등록합니다.

  • Step 1: Spring Boot 프로젝트(eureka-provider) 생성 후 의존성 추가: spring-cloud-starter-netflix-eureka-client, spring-boot-starter-web
  • Step 2: 메인 클래스에 @EnableDiscoveryClient 추가하여 Eureka 클라이언트 활성화
  • Step 3: application.properties 설정:
    # 서비스 이름 - 다른 서비스 호출 시 사용
    spring.application.name=eureka-provider
    # 서비스 포트
    server.port=2001
    
    # Eureka 서버 위치
    eureka.client.serviceUrl.defaultZone=http://localhost:1001/eureka/
    
  • Step 4: 컨트롤러 생성 - DiscoveryClient를 통해 서비스 정보 출력:
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.cloud.client.discovery.DiscoveryClient;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class ServiceInfoController {
    
        @Autowired
        private DiscoveryClient discoveryClient;
    
        @GetMapping("/info")
        public String getServiceInfo() {
            String services = "Registered Services: " + discoveryClient.getServices();
            System.out.println(services);
            return services;
        }
    }
    
  • Step 5: 프로젝트 실행 후 http://localhost:1001 접속 - Eureka 대시보드에서 등록된 서비스 확인 가능
  • Step 6: http://localhost:2001/info 접속 시 서비스 정보 확인

2. 서비스 컨슈머 구현 (기본 방식)

목표: LoadBalancerClient를 사용하여 서비스 프로바이더 호출

  • Step 1-3: 새 프로젝트(eureka-consumer) 생성 및 동일 의존성 추가, 포트 2101 설정
  • Step 4: RestTemplate 빈 등록:
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
    
  • Step 5: 컨트롤러 작성:
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.cloud.client.ServiceInstance;
    import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.client.RestTemplate;
    
    @RestController
    public class ConsumerController {
    
        @Autowired
        private LoadBalancerClient loadBalancerClient;
    
        @Autowired
        private RestTemplate restTemplate;
    
        @GetMapping("/consume")
        public String consumeService() {
            ServiceInstance instance = loadBalancerClient.choose("eureka-provider");
            String url = "http://" + instance.getHost() + ":" + instance.getPort() + "/info";
            System.out.println("Request URL: " + url);
            return restTemplate.getForObject(url, String.class);
        }
    }
    
  • Step 6: 서버(Eureka, Provider, Consumer) 실행 후 http://localhost:2101/consume 접속 시 호출 결과 확인

3. Ribbon을 활용한 서비스 소비

장점: @LoadBalanced 어노테이션으로 URL 조립 과정 생략

  • Step 1-3: 새 프로젝트(eureka-consumer-ribbon) 생성 후 의존성 추가: spring-cloud-starter-netflix-ribbon, 포트 2201
  • Step 4: RestTemplate 빈에 @LoadBalanced 추가:
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
    
  • Step 5: 컨트롤러 간소화:
    @RestController
    public class RibbonConsumerController {
    
        @Autowired
        private RestTemplate restTemplate;
    
        @GetMapping("/consume")
        public String consume() {
            return restTemplate.getForObject("http://eureka-provider/info", String.class);
        }
    }
    
  • Step 6: http://localhost:2201/consume 접속 시 Ribbon이 자동 로드밸런싱 수행

4. Feign을 이용한 선언적 서비스 호출

특징: 인터페이스 기반 선언으로 코드 간결화, 자동 로드밸런싱 및 Hystrix 지원

  • Step 1-3: 새 프로젝트(eureka-consumer-feign) 생성 후 의존성: spring-cloud-starter-openfeign, 포트 2301
  • Step 4: 메인 클래스에 @EnableFeignClients 추가
  • Step 5: Feign 클라이언트 인터페이스 정의:
    import org.springframework.cloud.openfeign.FeignClient;
    import org.springframework.stereotype.Service;
    import org.springframework.web.bind.annotation.GetMapping;
    
    @Service
    @FeignClient("eureka-provider")
    public interface ProviderClient {
    
        @GetMapping("/info")
        String getServiceInfo();
    }
    
  • Step 6: 컨트롤러에서 Feign 클라이언트 주입:
    @RestController
    public class FeignConsumerController {
    
        @Autowired
        private ProviderClient providerClient;
    
        @GetMapping("/consume")
        public String consume() {
            return providerClient.getServiceInfo();
        }
    }
    
  • Step 7: http://localhost:2301/consume 접속 시 Feign이 서비스 호출 실행

5. 다중 인스턴스 로드밸런싱 테스트

시나리오: 동일 서비스 이름으로 여러 인스턴스 실행 시 자동 부하 분산 확인

  • 프로젝트(eureka-provider-2) 생성 후 포트 2002로 설정, 서비스 이름은 eureka-provider 유지
  • 컨트롤러 응답을 다르게 작성:
    @GetMapping("/info")
    public String getInfo() {
        return "This is instance 2 - Services: " + discoveryClient.getServices();
    }
    
  • 모든 인스턴스 실행 후 http://localhost:2101/consume 반복 접속 시 교차 응답 확인 가능

방식 비교

방식URL 처리로드밸런싱코드 복잡도
기본 (LoadBalancerClient)수동 조립수동 선택높음
Ribbon자동 변환자동중간
Feign선언적내장낮음

세 가지 방식 모두 상호 대체 가능하며, Feign이 가장 간결한 코드 구조를 제공합니다.

태그: Spring Cloud Eureka Ribbon Feign LoadBalancerClient

6월 24일 02:52에 게시됨