Eureka: 서비스 레지스트리 및 검색 시스템 구축 🚀
마이크로서비스 아키텍처가 현대 소프트웨어 개발의 중심으로 자리 잡으면서, 서비스 디스커버리와 로드 밸런싱의 중요성이 더욱 부각되고 있습니다. 이러한 환경에서 Netflix Eureka는 강력하고 신뢰할 수 있는 서비스 레지스트리 및 검색 시스템으로 주목받고 있습니다. 이 글에서는 Eureka의 개념부터 구축 방법, 그리고 실제 운영에 이르기까지 상세히 다루어 보겠습니다. 🌟
💡 Tip: Eureka를 통한 서비스 레지스트리 구축은 마이크로서비스 아키텍처의 핵심 요소입니다. 이는 재능넷과 같은 복잡한 플랫폼에서 특히 유용할 수 있으며, 다양한 서비스 간의 원활한 통신과 확장성을 보장합니다.
1. Eureka 개요
Eureka는 AWS 클라우드에서 중간 계층 서버의 로드 밸런싱과 페일오버를 목적으로 Netflix에서 개발한 REST 기반 서비스입니다. 주요 특징은 다음과 같습니다:
- 서비스 등록 및 해제의 자동화
- 상태 모니터링을 통한 서비스 가용성 확인
- 분산 시스템에서의 고가용성 보장
- 클라이언트 측 로드 밸런싱 지원
Eureka는 서비스 인스턴스의 동적인 추가 및 제거를 지원하여, 클라우드 환경에서의 탄력적인 확장을 가능하게 합니다.
위 다이어그램은 Eureka 서버를 중심으로 여러 마이크로서비스가 등록되고 상호작용하는 모습을 보여줍니다. 각 서비스는 Eureka 서버에 자신의 정보를 등록하고, 필요할 때 다른 서비스의 정보를 조회할 수 있습니다.
2. Eureka 서버 구축
Eureka 서버를 구축하는 과정은 다음과 같습니다:
- Spring Boot 프로젝트 생성
- 의존성 추가
- 애플리케이션 설정
- Eureka 서버 활성화
2.1 Spring Boot 프로젝트 생성
Spring Initializr를 사용하여 새로운 Spring Boot 프로젝트를 생성합니다. 프로젝트 생성 시 다음 설정을 선택합니다:
- Project: Maven Project
- Language: Java
- Spring Boot: 2.5.x 이상
- Packaging: Jar
- Java: 11 이상
2.2 의존성 추가
pom.xml 파일에 Eureka 서버 의존성을 추가합니다:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
또한, Spring Cloud 버전을 관리하기 위해 다음 속성을 추가합니다:
<properties>
<spring-cloud.version>2020.0.3</spring-cloud.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
2.3 애플리케이션 설정
application.properties 또는 application.yml 파일에 Eureka 서버 설정을 추가합니다:
server.port=8761
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
eureka.server.wait-time-in-ms-when-sync-empty=0
이 설정은 다음을 의미합니다:
- 서버 포트를 8761로 설정 (Eureka의 기본 포트)
- 자기 자신을 Eureka 서버에 등록하지 않도록 설정
- 레지스트리 정보를 로컬에 캐싱하지 않도록 설정
- 초기 동기화 대기 시간을 0으로 설정
2.4 Eureka 서버 활성화
메인 애플리케이션 클래스에 @EnableEurekaServer 어노테이션을 추가하여 Eureka 서버를 활성화합니다:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
이제 애플리케이션을 실행하면 Eureka 서버가 구동됩니다. 브라우저에서 http://localhost:8761로 접속하면 Eureka 대시보드를 확인할 수 있습니다.
3. Eureka 클라이언트 구현
Eureka 서버가 준비되었다면, 이제 Eureka 클라이언트를 구현하여 서비스를 등록해 보겠습니다. Eureka 클라이언트는 서비스 인스턴스를 Eureka 서버에 등록하고, 필요할 때 다른 서비스의 정보를 조회하는 역할을 합니다.
3.1 클라이언트 프로젝트 설정
새로운 Spring Boot 프로젝트를 생성하고, 다음 의존성을 추가합니다:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
3.2 애플리케이션 설정
application.properties 또는 application.yml 파일에 다음 설정을 추가합니다:
spring.application.name=my-service
server.port=8080
eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
이 설정은 다음을 의미합니다:
- 서비스 이름을 'my-service'로 설정
- 서비스 포트를 8080으로 설정
- Eureka 서버의 URL을 지정
3.3 Eureka 클라이언트 활성화
메인 애플리케이션 클래스에 @EnableDiscoveryClient 어노테이션을 추가하여 Eureka 클라이언트를 활성화합니다:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class MyServiceApplication {
public static void main(String[] args) {
SpringApplication.run(MyServiceApplication.class, args);
}
}
이제 애플리케이션을 실행하면 자동으로 Eureka 서버에 등록됩니다. Eureka 대시보드에서 등록된 서비스를 확인할 수 있습니다.
4. Eureka의 고가용성 구성
실제 운영 환경에서는 단일 Eureka 서버로는 충분하지 않습니다. 고가용성을 보장하기 위해 Eureka 서버를 클러스터로 구성해야 합니다. 이를 통해 한 서버가 다운되더라도 시스템이 계속 작동할 수 있습니다.
4.1 Eureka 서버 클러스터 구성
Eureka 서버 클러스터를 구성하려면 각 서버가 서로를 인식하도록 설정해야 합니다. 예를 들어, 두 개의 Eureka 서버를 구성한다고 가정해 봅시다.
첫 번째 Eureka 서버 (eureka-server-1) 설정:
spring.application.name=eureka-server-1
server.port=8761
eureka.instance.hostname=eureka-server-1
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
eureka.client.service-url.defaultZone=http://eureka-server-2:8762/eureka/
두 번째 Eureka 서버 (eureka-server-2) 설정:
spring.application.name=eureka-server-2
server.port=8762
eureka.instance.hostname=eureka-server-2
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
eureka.client.service-url.defaultZone=http://eureka-server-1:8761/eureka/
이 설정을 통해 두 Eureka 서버는 서로를 피어로 인식하고 정보를 동기화합니다.
4.2 클라이언트 설정 변경
클라이언트 애플리케이션에서는 모든 Eureka 서버의 주소를 지정해야 합니다:
eureka.client.service-url.defaultZone=http://eureka-server-1:8761/eureka/,http://eureka-server-2:8762/eureka/
이렇게 설정하면 클라이언트는 두 Eureka 서버 중 하나가 다운되어도 다른 서버를 통해 서비스 디스커버리를 계속할 수 있습니다.
5. Eureka의 자가 보호 모드
Eureka는 네트워크 문제나 기타 이슈로 인해 등록된 인스턴스들과의 통신이 어려워질 때 "자가 보호 모드(Self-Preservation Mode)"로 전환됩니다. 이 모드에서 Eureka는 등록된 인스턴스들의 정보를 계속 유지하며, 일시적인 네트워크 문제로 인해 서비스가 제거되는 것을 방지합니다.
5.1 자가 보호 모드의 작동 원리
- Eureka 서버는 클라이언트로부터 주기적으로 하트비트를 받습니다.
- 일정 시간 동안 예상된 하트비트의 수보다 적은 수의 하트비트를 받으면 자가 보호 모드로 전환됩니다.
- 자가 보호 모드에서는 인스턴스 등록 정보를 삭제하지 않고 유지합니다.
- 네트워크 상태가 정상화되면 자동으로 일반 모드로 복귀합니다.
5.2 자가 보호 모드 설정
자가 보호 모드는 기본적으로 활성화되어 있지만, 필요에 따라 비활성화할 수 있습니다:
eureka.server.enable-self-preservation=false
주의: 자가 보호 모드를 비활성화하면 일시적인 네트워크 문제로 인해 서비스가 불필요하게 제거될 수 있으므로 신중하게 결정해야 합니다.
6. Eureka와 Spring Cloud의 통합
Spring Cloud는 Eureka와 완벽하게 통합되어 있어, 마이크로서비스 아키텍처를 구현하는 데 필요한 다양한 기능을 제공합니다. 이 섹션에서는 Spring Cloud와 Eureka를 함께 사용하여 얻을 수 있는 이점과 주요 기능들을 살펴보겠습니다.
6.1 Spring Cloud Netflix
Spring Cloud Netflix 프로젝트는 Netflix OSS와 Spring Boot 애플리케이션을 쉽게 통합할 수 있게 해줍니다. Eureka 외에도 다음과 같은 컴포넌트들을 제공합니다:
- Ribbon: 클라이언트 측 로드 밸런싱
- Hystrix: 서킷 브레이커 패턴 구현
- Zuul: API 게이트웨이
6.2 서비스 디스커버리와 로드 밸런싱
Spring Cloud와 Eureka를 사용하면 서비스 디스커버리와 로드 밸런싱을 쉽게 구현할 수 있습니다. 예를 들어, @LoadBalanced 어노테이션을 사용하여 RestTemplate을 생성하면 자동으로 클라이언트 측 로드 밸런싱이 적용됩니다:
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
이제 이 RestTemplate을 사용하여 서비스 이름으로 다른 서비스를 호출할 수 있습니다:
restTemplate.getForObject("http://user-service/users/{id}", User.class, id);
6.3 Spring Cloud Config
Spring Cloud Config를 Eureka와 함께 사용하면 중앙 집중식 설정 관리를 구현할 수 있습니다. 설정 서버를 Eureka에 등록하고, 각 마이크로서비스가 설정 서버를 통해 설정을 동적으로 가져올 수 있습니다.
6.4 Spring Cloud Gateway
Spring Cloud Gateway는 Zuul의 대안으로, API 게이트웨이 역할을 수행합니다. Eureka와 통합하여 동적 라우팅, 보안, 모니터링 등의 기능을 제공할 수 있습니다.
7. Eureka의 모니터링과 관리
Eureka 서버와 클라이언트의 효과적인 운영을 위해서는 적절한 모니터링과 관리가 필수적입니다. 이 섹션에서는 Eureka의 모니터링 방법과 관리 도구에 대해 알아보겠습니다.
7.1 Eureka 대시보드
Eureka 서버는 기본적으로 웹 기반 대시보드를 제공합니다. 이 대시보드에서 다음과 같은 정보를 확인할 수 있습니다:
- 등록된 인스턴스 목록
- 인스턴스의 상태 정보
- Eureka 서버의 상태 정보
대시보드 URL: http://<eureka-server-host>:<port>/
7.2 Spring Boot Actuator
Spring Boot Actuator를 사용하면 Eureka 서버와 클라이언트의 상태를 더 자세히 모니터링할 수 있습니다. Actuator 엔드포인트를 활성화하려면 다음 의존성을 추가하세요:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
주요 Actuator 엔드포인트:
- /actuator/health: 애플리케이션의 건강 상태
- /actuator/info: 애플리케이션 정보
- /actuator/metrics: 메트릭 정보
7.3 Prometheus와 Grafana
Prometheus와 Grafana를 사용하여 Eureka의 메트릭을 수집하고 시각화할 수 있습니다. Spring Boot Actuator는 Prometheus 형식의 메트릭을 제공합니다.
- Prometheus 설정:
scrape_configs: - job_name: 'eureka' metrics_path: '/actuator/prometheus' static_configs: - targets: ['eureka-server:8761']
- Grafana에서 Prometheus 데이터 소스를 추가하고 대시보드를 생성하여 메트릭을 시각화합니다.
7.4 로깅
적절한 로깅 설정은 문제 해결과 모니터링에 중요합니다. Eureka 서버와 클라이언트의 로그 레벨을 조정하여 필요한 정보를 얻을 수 있습니다:
logging.level.com.netflix.eureka=DEBUG
logging.level.com.netflix.discovery=DEBUG