Loading the catalog…
Loading the catalog…
1. 한 줄 요약 Service Discovery는 계속 변하는 서비스 인스턴스의 위치를 등록하고 검색하는 기능이며, Spring Cloud Netflix Eureka를 사용하면 마이크로서비스가 자신의 정보를 등록하고 다른 서비스가 논리적인 서비스 이름으로 인스턴스를 찾을 수 있다. 2. 배운 내용 Service Discovery가 필요한 이유 모놀리식 애플리케이션은 대부분 하나의 주소로 요청을 전달하므로 호출할 서버의 위치를 파악하기 어렵지 않다. 반면 MSA에서는 같은 서비스를 여러 인스턴스로 실행할 수 있고, 확장이나 장애 복구 과정에서 인스턴스의 주소와 포트가 계속 바뀔 수 있다. 예를 들어 user-service 가 다음과 같이 실행될 수 있다. user-service:60000 user-service:60001 user-service:60002 호출하는 서비스가 이 주소들을 코드나 설정에 직접 작성하면 인스턴스가 추가되거나 제거될 때마다 설정을 변경해야 한다. Service Discovery를 사용하면 각 인스턴스가 중앙의 Service Registry에 자신의 위치를 등록한다. 다른 서비스나 Load Balancer는 Registry를 조회해 현재 요청을 처리할 수 있는 인스턴스를 찾는다. 서비스 인스턴스 ↓ 등록 Service Registry ↑ 조회 호출 서비스 또는 Load Balancer 내가 이해한 Service Discovery는 전화번호를 모두 외우는 대신 이름과 현재 전화번호를 관리하는 연락처를 조회하는 것과 비슷하다. Eureka Server와 Eureka Client Spring Cloud Netflix Eureka는 Service Discovery를 구현하기 위한 Server와 Client를 제공한다. Eureka Server Eureka Server는 서비스 인스턴스 정보를 저장하는 Service Registry 역할을 한다. 서비스 이름 호스트 주소 포트 상태 정보 서비스의 메타데이터 Eureka Client 각 마이크로서비스는 Eureka Client가 되어 자신의 정보를 Eureka Server에 등록한다. 등록된 서비스는 다른 서비스의 위치를 조회할 수도 있다. 같은 서비스가 여러 인스턴스로 실행되면 Load Balancer는 Eureka에 등록된 인스턴스 목록을 바탕으로 요청을 분산할 수 있다. Eureka Server 프로젝트 생성 강의에서는 다음 환경으로 Service Discovery 프로젝트를 생성했다. Java 21 Spring Boot 3.5.0 Spring Cloud 2025.0.0 Eureka Server Spring Boot와 Spring Cloud는 아무 버전이나 조합할 수 있는 것이 아니다. Spring Cloud의 Release Train마다 호환되는 Spring Boot 세대가 정해져 있으므로 프로젝트를 생성할 때 버전 호환성을 확인해야 한다. Eureka Server를 사용하기 위해 다음 의존성을 추가한다. <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> 메인 클래스에는 @EnableEurekaServer 를 선언한다. @SpringBootApplication @EnableEurekaServer public class ServiceDiscoveryApplication { public static void main(String[] args) { SpringApplication.run( ServiceDiscoveryApplication.class, args ); } } @EnableEurekaServer 를 사용하면 해당 Spring Boot 애플리케이션이 Eureka Server로 동작한다. Eureka Server 설정 Eureka Server는 기본적으로 8761 번 포트를 사용하도록 설정했다. server: port: 8761 spring: application: name: service-discovery eureka: client: register-with-eureka: false fetch-registry: false 각 설정의 의미는 다음과 같다. register-with-eureka: false 현재 애플리케이션은 서비스를 등록받는 Eureka Server이므로 자기 자신을 Eureka Registry에 등록하지 않도록 설정한다. fetch-registry: false Eureka Client가 다른 서비스 목록을 가져오는 기능을 사용하지 않도록 설정한다. 단일 Eureka Server 실습에서는 다른 Eureka Server의 Registry 정보를 가져올 필요가 없으므로 두 값을 모두 false 로 설정했다. 애플리케이션을 실행한 뒤 다음 주소에 접속하면 Eureka 대시보드를 확인할 수 있다. http://localhost:8761 처음에는 등록된 서비스가 없기 때문에 인스턴스 목록이 비어 있다. User Service를 Eureka Client로 등록하기 User Service에는 Eureka Client 의존성을 추가했다. <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> 강의에서는 메인 클래스에 @EnableDiscoveryClient 를 선언했다. @SpringBootApplication @EnableDiscoveryClient public class UserServiceApplication { public static void main(String[] args) { SpringApplication.run( UserServiceApplication.class, args ); } } 현재 Spring Cloud에서는 Eureka Client Starter가 클래스 경로에 있으면 자동 설정을 통해 Eureka Client로 동작할 수 있어 @EnableDiscoveryClient 가 필수는 아니다. 다만 강의에서는 Discovery Client임을 명시적으로 표현하기 위해 사용했다. User Service의 설정은 다음과 같다. server: port: 60000 spring: application: name: user-service eureka: client: service-url: defaultZone: http://127.0.0.1:8761/eureka fetch-registry: true register-with-eureka: true spring.application.name 은 Eureka에 등록되는 서비스의 논리적인 이름으로 사용된다. defaultZone 에는 Eureka Server의 주소를 지정한다. 현재 공식 문서에서는 defaultZone 의 대소문자가 구분되므로 정확한 이름을 사용해야 한다. User Service를 실행하면 Eureka 대시보드에 다음과 같이 등록된다. Application: USER-SERVICE Status: UP Port: 60000 같은 서비스의 인스턴스 확장하기 MSA에서는 하나의 서비스를 여러 인스턴스로 실행해 트래픽을 분산하거나 가용성을 높일 수 있다. 하지만 동일한 애플리케이션을 그대로 다시 실행하면 이미 사용 중인 포트 때문에 실행에 실패한다. Web server failed to start. Port 60000 was already in use. 하나의 IP와 포트 조합에는 하나의 서버만 바인딩할 수 있기 때문에 추가 인스턴스는 다른 포트를 사용해야 한다. IntelliJ VM Options 사용 두 번째 인스턴스의 실행 설정에 다른 포트를 지정한다. -Dserver.port=60001 Maven으로 실행 mvn spring-boot:run \ -Dspring-boot.run.jvmArguments="-Dserver.port=60002" 빌드된 JAR 파일 실행 mvn clean package java -Dserver.port=60003 -jar ./target/user-service-1.0.jar 각 인스턴스가 실행되면 Eureka에는 하나의 USER-SERVICE 아래 여러 인스턴스가 등록된다. USER-SERVICE ├── user-service:60000 ├── user-service:60001 ├── user-service:60002 └── user-service:60003 서비스를 호출하는 쪽은 물리적인 포트를 직접 선택하는 대신 USER-SERVICE 라는 논리적인 이름을 사용할 수 있다. Random Port 사용하기 인스턴스를 실행할 때마다 포트를 직접 지정하지 않고 운영체제가 사용 가능한 포트를 자동으로 할당하도록 설정할 수도 있다. server: port: 0 spring: application: name: user-service server.port 를 0 으로 설정하면 애플리케이션이 실행될 때 사용 가능한 임의의 포트가 할당된다. Tomcat started on port 53308 Tomcat started on port 53317 이 방식은 여러 인스턴스를 반복해서 실행할 때 포트 충돌을 피할 수 있다는 장점이 있다. Random Port 사용 시 Instance ID 문제 Random Port를 사용해 같은 서비스를 여러 번 실행했지만, Eureka 대시보드에서 인스턴스가 하나만 등록되는 문제가 발생했다. 두 애플리케이션의 서비스 이름과 기본 Instance ID가 같아 Eureka가 서로 다른 인스턴스로 구분하지 못했기 때문이다. 각 인스턴스에 고유한 ID를 설정해 문제를 해결할 수 있다. server: port: 0 spring: application: name: user-service eureka: instance: instance-id: ${spring.application.name}:${spring.application.instance_id:${random.value}} client: service-url: defaultZone: http://127.0.0.1:8761/eureka 설정값은 다음 순서로 Instance ID를 만든다. spring.application.name 을 사용한다. spring.application.instance_id 가 있으면 해당 값을 사용한다. 값이 없으면 random.value 로 고유한 값을 만든다. 따라서 모든 인스턴스가 같은 user-service 라는 서비스 이름을 사용하면서도 각각 고유한 인스턴스로 등록될 수 있다. user-service:고유한 값 1 user-service:고유한 값 2 서비스 이름은 같은 기능을 제공하는 인스턴스를 묶는 기준이고, Instance ID는 그 안에서 각각의 실행 인스턴스를 구별하는 값이라고 이해했다. Service Discovery와 Load Balancing의 관계 Service Discovery와 Load Balancing은 비슷하게 느껴지지만 역할이 다르다. Service Discovery 현재 실행 중인 서비스 인스턴스가 어디에 있는지 관리하고 검색한다. Load Balancing Service Discovery에서 얻은 여러 인스턴스 중 하나를 선택해 요청을 분산한다. 클라이언트 요청 ↓ Load Balancer ↓ Eureka에서 인스턴스 목록 조회 ┌──────────┬──────────┬──────────┐ │ 60000번 │ 60001번 │ 60002번 │ └──────────┴──────────┴──────────┘ Eureka가 직접 모든 요청을 중계하는 것이 아니라 서비스의 위치 정보를 관리하고, 실제 요청 분산은 Spring Cloud LoadBalancer 같은 별도의 구성 요소가 담당한다. 3. 실습 / 적용 오늘 실습에서는 다음 순서로 Eureka 기반 Service Discovery 환경을 구성했다. Eureka Server 프로젝트를 생성했다. @EnableEurekaServer 로 Eureka Server를 활성화했다. 8761 번 포트에서 Eureka 대시보드를 실행했다. User Service에 Eureka Client 의존성을 추가했다. User Service를 Eureka Server에 등록했다. 서로 다른 포트를 사용해 여러 인스턴스를 실행했다. Eureka 대시보드에서 인스턴스가 함께 등록되는 것을 확인했다. server.port: 0 으로 Random Port를 사용했다. 고유한 instance-id 를 지정해 각 인스턴스를 구분했다. 4. 문제와 해결 문제 1: 추가 인스턴스 실행 시 포트 충돌 발생한 문제 같은 User Service를 추가로 실행했지만 기존 인스턴스가 사용 중인 60000 번 포트와 충돌했다. Port 60000 was already in use. 원인 같은 컴퓨터에서 동일한 IP와 포트를 사용하는 서버를 동시에 실행하려고 했다. 해결 방법 각 인스턴스에 서로 다른 포트를 지정했다. -Dserver.port=60001 -Dserver.port=60002 -Dserver.port=60003 또는 server.port: 0 으로 설정해 실행할 때마다 사용 가능한 포트를 자동으로 할당받았다. 문제 2: Random Port 인스턴스가 하나만 등록됨 발생한 문제 Random Port를 사용해 여러 인스턴스를 실행했지만 Eureka에서는 하나의 인스턴스만 보였다. 원인 포트는 달랐지만 Eureka가 인스턴스를 구분하는 Instance ID가 동일했다. 해결 방법 eureka.instance.instance-id 에 임의의 값을 포함해 각 인스턴스가 고유한 ID를 갖도록 설정했다. eureka: instance: instance-id: ${spring.application.name}:${spring.application.instance_id:${random.value}} 문제 3: Spring Boot와 Spring Cloud 버전 선택 Spring Boot와 Spring Cloud의 버전을 독립적으로 선택하면 호환성 문제가 발생할 수 있다. 강의에서는 Spring Boot 3.5.0 과 Spring Cloud 2025.0.0 을 함께 사용했다. 공식 호환표에서도 Spring Cloud 2025.0.x 는 Spring Boot 3.5.x 세대와 대응한다. 실제 프로젝트에서는 강의의 초기 버전을 그대로 고정하기보다, 같은 Release Train 안에서 지원되는 최신 서비스 릴리스와 공식 호환표를 확인해야 한다. 5. 다음에 할 일 Eureka에 등록된 서비스 이름으로 다른 서비스를 호출해보기 Spring Cloud LoadBalancer의 요청 분산 방식 알아보기 Eureka Client의 Heartbeat와 인스턴스 제거 과정 공부하기 여러 Eureka Server를 구성하는 고가용성 방식 알아보기 API Gateway와 Eureka를 연결해 동적 라우팅 구현하기 참고 자료 Spring Cloud Netflix 공식 문서 Spring Cloud 공식 페이지 및 버전 호환표 Spring Initializr
What RADAR observed and classified to build this opportunity. It is what the source published, not a verification that the offer is still active.
[LG CNS AM 6기] 39일차 TIL - Eureka로 Service Discovery 구현하기. 1. 한 줄 요약 Service Discovery는 계속 변하는 서비스 인스턴스의 위치를 등록하고 검색하는 기능이며, Spring Cloud Netflix Eureka를 사용하면 마이크로서비스가 자신의 정보를 등록하고 다른 서비스가 논리적인 서비스 이름으로 인스턴스를 찾을 수 있다. 2. 배운 내용 Service Discovery가 필요한 이유 모놀리식 애플리케이션은 대부분 하나의 주소로 요청을 전달하므로 호출할 서버의 위치를 파악하기 어렵지 않다. 반면 MSA에서는 같은 서비스를 여러 인스턴스로 실행할 수 있고, 확장이나 장애 복구 과정에서 인스턴스의 주소와 포트가 계속 바뀔 수 있다. 예를 들어…
Open source