Eureka 서버 등록

Jiyeon·2024년 5월 3일

ninishop

목록 보기
2/6
  • MSA로 리팩토링 하는 과정에서 Eureka를 사용함으로써 모듈이름을 정해줄 수 있었고,
    정해놓은 이름을 여기저기 모듈을 구분하는 데에 쓸 수있어서 개발 하는 과정이 조금 더 직관적이고 편했다고 느낌, Ex) api-gateway 설정할때 Eureka에 등록한 서버이름으로 명시 가능

Eureka란

클라우드 환경의 다수의 서비스(예: API서버)들의 로드밸런싱 및 장애 조치 목적을 가진 미들웨어 서버

  • Eureka는 이러한 미들웨어 기능을 하기 위해 각 연결된 서비스의 IP / PORT /InstanceId를 가지고 있고 REST기반으로 작동
  • Client-Sever 방식으로 Eureka Server에 등록된 서비스는 Eureka Client로 불림

로드 밸런싱 : 특정 서비스를 제공하는 서버가 여러대가 있을 때 트래픽을 한 서버에 몰리지 않게 분산 해주는 기술
미들웨어 : 데이터를 주고 받는 양쪽의 서비스(예: 클라이언트와 API서버)의 중간에 위치해 매개 역할을 하는 소프트웨어

▲ Eureka Server와 Eureka Client의 프로세스

  • 서비스를 Eureka Server에 등록하게 되면 Eureka Server는 각 Eureka Client의 IP / PORT / InstanceId 를 저장
  • 이후 Eureka Client가 다른 Eureka Client에게 요청을 보낼 때 Eureka에서 받아온 정보를 가지고 요청을 보낼 수 있다.

Eureka 서버등록

  • build.gradle

plugins {
	id 'java'
	id 'org.springframework.boot' version '3.2.5'
	id 'io.spring.dependency-management' version '1.1.4'
}

group = 'org.example'
version = '0.0.1-SNAPSHOT'

java {
	sourceCompatibility = '21'
}

ext { // 프로젝트의 확장 속성을 설정 
// springCloudVersion이라는 이름으로 "2023.0.0"이라는 값을 설정
// 전체 스크립트에서 springCloudVersion을 사용해서 참조가능
	set('springCloudVersion', "2023.0.0")
}

dependencies {
	implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-server'
	implementation 'org.springframework.boot:spring-boot-starter-actuator'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

// 의존성 관리를 위한 설정
// mavenBom을 사용해서 스프링 클라우드 프로젝트의 모든 의존성을 한번에 관리할 수 있도록 설정
// ${springCloudVersion}을 사용해서 위에서 정의한 스프링 클라우드의 버전을 적용
dependencyManagement {
	imports {
		mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
	// BOM(Bill of Materials): 여러 라이브러리의 호환되는 버전을 미리 정의해 놓은 것 
	}
}

repositories {
	mavenCentral()
}

tasks.named('test') {
	useJUnitPlatform()
}

  • application.yml
server:
  port: 8761

spring:
  application:
    name: eureka-server

eureka:
  client:
    register-with-eureka: false # 현재 서비스를 eureka server에 등록 여부
    
     # 다른 서비스들의 정보를 eureka server로 부터 받아서 로컬메모리에 캐싱할지 여부
    fetch-registry: false
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/ # Eureka Server URL지정 Eureka API 요청용 URL

  server:
    # 서버가 요청을 받기 전 대기할 초기 시간(ms)
    # default 5분 : 실무에서는 보통 모든 서비스가 등록 되길 기다리기 위해 5분 후 정보를 공유
    # 개인 프로젝트인 만큼 빠른 등록을 위해 5ms로 설정
    wait-time-in-ms-when-sync-empty: 5

management:
  endpoints:
    web:
      exposure:
        include: "*" # Spring Actuator의 어떤 API를 사용할 지 지정하는 설정, * : 우선 모든 API사용

유레카 설정을 마치고 대시보드에 접속

경고메세지
EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY'RE NOT. RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEING EXPIRED JUST TO BE SAFE.

➡️ 유레카 대시보드에서 흔히 볼 수 있는 문구
유레카 서버가 운영중에 서비스 인스턴스들의 상태에 대해 잘못된 정보를 보고할 수 있다는 경고
EX ) 실제로는 동작하지 않는 인스턴스를 정상 동작한다고 인식할 가능성이 있다


이경고표시의 주된 원인

  • 유레카서버가 받는 인스턴스의 갱신( heartbeat)수가 설정된 임계값보다 적기 때문
  • 유레카 서버는 등록된 모든 인스턴스로부터 일정시간 간격으로 heartbeats를 받아야함
  • heartbeats : 인스턴스가 여전히 살아있고 정상적으로 동작하고 있음을 유레카 서버에 알리는 신호

유레카 서버가 충분한 수의 heartbeats를 받지 못한다면 발생할 수 있는 상황

  • 실제로 인스턴스가 다운되었지만, 유레카서버는 잘못된 정보를 기반으로 인스턴스가 여전히 동작한다고 판단할 수 있음
  • 네트워크 문제나 기타이 이유로 heartbeats가 지연되는 경우, 유레카는 임시적으로 인스턴스를 유지하면서 상황을 주시

문제 해결 방법
  1. 인스턴스 수 확인 : 유레카서버에 등록된 인스턴스 수가 매우 적은 경우(특히 개발환경)
  2. 임계값 조정 : eureka.instance.leaseRenewalIntervalInSecondseureka.instance.leaseExpirationDurationInSeconds 설정을 조정하여 인스턴스의 heartbeats 간격과 만료 시간을 조절
  3. 서버로그 확인 : 인스턴스들이 유레카서버와 제대로 통신하고있는지, 혹은 다른 네트워크 이슈가 있는 지 확인

Eureka Clients 구현

각 Service 마다 Eureka Clients 추가해주기

  • build.gradle
  ext {
    set('springCloudVersion', "2023.0.0")
}

dependencies {
    // eureka-client 외의 서비스에 필요한 의존성들
    ...
    
    // Eureka Clients 의존성
    implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'
    // 스프링 엑추에이터
    implementation 'org.springframework.boot:spring-boot-starter-actuator'
}

dependencyManagement {
    imports {
        mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
    }
}



  • application.yml
server:
port: 8011

spring:
  application:
    name: user-service

eureka:
  instance:
    prefer-ip-address: true # 서비스의 호스트이름이 아닌 ip주소를 유레카서버에 등록 할지 여부
    # 배포환경에서 DNS가 존재하면 할당받은 호스트이름을 Eureka서버에 등록하면 되지만 컨테이너 기반의 배포환경일 경우
    # 컨테이너가 DNS 엔트리가 없는 임의의 호스트이름이 부여되기 때문에 false로 설정시 유레카서버가 해당 서비스의 호스트 이름위치를 정상적으로 얻지 못함
	# 따라서, 컨테이너 기반 배포라면 해당 옵션을 true로 하여 Eureka Server가 서비스를 IP 주소로 등록해서 찾게하기 
  client:
    register-with-eureka: true # Eureka server에 현재서비스를 등록할지 여부
    fetch-registry: true # Eureka server에 등록되어있는 서비스들을 캐싱해둘지 여부 
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/

management:
  endpoints:
    web:
      exposure:
        include: "*"

prefer-ip-address : true

  • 서비스의 호스트이름이 아닌 ip주소를 유레카서버에 등록 할지 여부
  • 배포환경에서 DNS가 존재하면 할당받은 호스트이름을 Eureka서버에 등록하면 되지만
    컨테이너 기반의 배포환경일 경우 컨테이너가 DNS 엔트리가 없는 임의의 호스트이름이 부여되기 때문에 false로 설정시 유레카서버가 해당 서비스의 호스트 이름위치를 정상적으로 얻지 못함
  • 따라서, 컨테이너 기반 배포라면 해당 옵션을 true로 하여 Eureka Server가 서비스를 IP 주소로 등록해서 찾게하기
  • UserServiceAppication.class
@EnableDiscoveryClient // 어노테이션 넣기
@SpringBootApplication
public class UserServiceApplication {

    public static void main(String[] args) {
        SpringApplication.run(UserServiceApplication.class, args);
    }

}
profile
개발자

0개의 댓글