spring cloud - eureka 기본 설정!

https://github.com/Kouzie/sample-spring-cloud

https://coe.gitbook.io/guide/service-discovery/eureka

eureka 개요

바야흐로 클라우드 시대, 서버는 실제 서버 컴퓨터에서 돌아가지않고 아마존과 같은 호스팅 업체가 관리하는 클라우드 서버에서 실행된다.

서버 IP는 유동적으로 변경되고 서버 관리자는 이에 대한 조치를 일일이 하기 힘듬으로 동적으로 이동하는 서버(eureka client)를 관리하는 서버(eureka server)를 구성하여 조치한다.

이렇게 실제 클라이언트의 요청을 처리하는 서버(eureka client)들 사이에서 Middle-tier(중간다리) 역할을 하는것이 eureka server이다.

eureka client 관리뿐 아니라 로드 밸런싱이나 장애 복구 기능까지 제공한다.

eureka_discovery

eureka 용어

Eureka 행동 관련

Service Registry: 서비스(eureka client)가 자기 자신의 정보를 Eureka Server에 등록하는 행동

Service Discovery: 클라이언트가 요청을 보내면 Service Registry 되어있는 서비스 들을 Eureka Server에서 발견하는 과정

Eureka 구성 요소 관련

Eureka Server: Eureka Client들을 관리(등록, 제어, 삭제, 제공) 하는 서버

Eureka Client: Service Registry 하여 서비스에 대한 비지니스 로직을 처리하는 클라이언트, 다른 Eureka Client 들과 연동하여 비지니스 로직을 처리한다.

Eureka Service: Eureka Server에 등록된 서비스를 가리킴, Eureka Client가 제공하는 서비스로 하나의 서비스의 원활한 수행을 위해 동시에 같은 서비스를 지원하는 여러개의 Eureka Client 가 동작할 수 있다.

Eureka Instance: Eureka에 등록되어 목록에서 조회 가능한 Eureka Service를 의미

Netflix Eureka 구성

eureka_tbd

위 그림은 Netflix에서 Eureka를 어떻게 사용하고 있는지에대한 그림

spring-cloud 버전 - 릴리즈 트레인

MODULE VERSION
Spring Cloud Task 2.1.2.RELEASE
Spring Cloud Config 2.1.3.RELEASE
Spring Cloud Sleuth 2.1.2.RELEASE
Spring Cloud Commons 2.1.2.RELEASE
Spring Cloud Openfeign 2.1.2.RELEASE
Spring Cloud Kubernetes 1.0.2.RELEASE
Spring Cloud Aws 2.1.2.RELEASE
Spring Cloud Vault 2.1.2.RELEASE
Spring Cloud Function 2.0.2.RELEASE
Spring Cloud Bus 2.1.2.RELEASE
Spring Cloud Build 2.1.6.RELEASE
Spring Cloud Zookeeper 2.1.2.RELEASE
Spring Cloud Gcp 1.1.2.RELEASE
Spring Cloud Contract 2.1.2.RELEASE
Spring Cloud Consul 2.1.2.RELEASE
Spring Cloud Security 2.1.3.RELEASE
Spring Cloud Gateway 2.1.2.RELEASE
Spring Cloud Cloudfoundry 2.1.2.RELEASE
Spring Cloud Netflix 2.1.2.RELEASE
Spring Cloud Stream Fishtown.SR3

Spring Cloud 안에는 Eureka이외에도 여러개의 프로젝트가 존재하며 서로 의존관계가 형성되는 경우가 많다.

하지만 버전은 각기 다르고 이를 외우고 다닐수 없으니 통합으로 사용하는 버전이 있는데 릴리즈 트레인이다.

영국의 지하철 명을 버전명으로 사용하며 스프링 부트 버전에 맞는 릴리즈 트레인 명을 찾아 Spring Cloud를 사용하면 된다.

Release Train Boot Version
Hoxton 2.2.x
Greenwich 2.1.x
Finchley 2.0.x
Edgware 1.5.x
Dalston 1.5.x

Release Train 에 맞춰 자동으로 스프링 클라우드 관련 dependency 버전이 설정된다.

현재 Spring Boot버전은 2.2.6.RELEASE을 사용하고 있으며 Spring Cloud버전은 Hoxton.SR4을 사용중이다.

eureka 프로젝트 생성

현 스프링 부트 버전: 2.2.6.RELEASE

eureka 서버 설정

eureka_registry

먼저 eureka client들이 서버에 register할 수 있도록 서버를 먼저 생성하자.

  • Spring Boot Tool
  • Spring Web
  • Eureka Server

위 3개의 dependencyIntelliJ 프로젝트 생성시 포함,
아래와 같은 pom.xml이 생성된다.

...
...
<properties>
    <java.version>1.8</java.version>
    <spring-cloud.version>Greenwich.SR3</spring-cloud.version>
</properties>

<dependencies>
    ...
    ...
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
    </dependency>
</dependencies>

<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>

application.properties는 아래와 같이 설정

spring-cloud-starter-netflix-eureka-server dependencyserver기능 뿐 아니라 client의 기능도 의존설정되어 있는데 클라이언트의 discovery기능을 제거한다.

서버 자신이 다른서버에 discovery 되지 않도록 아래 proeprties 설정

server.port=${PORT:8761}
# 유레카 서버에 본인 서비스를 등록할 건지 여부
eureka.client.register-with-eureka=true
# 유레카 서버로부터 서비스 목록을 로컬 캐시에 저장할 건지 여부, 둘 다 기본값 true라서 지정하지 않아도 상관 없다.
eureka.client.fetchRegistry=true

마지막으로 main클래스 위에 @EnableEurekaServer 어노테이션을 지정하고 실행하면 유레카 서버의 역할을 수행한다.

@SpringBootApplication
@EnableEurekaServer
public class EurekaserverApplication {
    public static void main(String[] args) {...}
}

eureka 클라이언트 설정

서비스를 유레카 서버에 등록하는 유레카 클라이언트 생성과정을 알아보자.
프로젝트 생성시 IntelliJ에서 다음 dependency추가,

  • Spring Boot Tool
  • Spring Web
  • Eureka Discovery Client
...
...
<properties>
    <java.version>1.8</java.version>
    <spring-cloud.version>Greenwich.SR3</spring-cloud.version>
</properties>
<dependencies>
    ...
    ...
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
</dependencies>

spring-cloud-starter-netflix-eureka-client dependency 가 추가된다.

server.port=${PORT:8081}
spring.application.name=demo_eureka_client
eureka.client.service-url.defaultZone=${EUREKA_URL:http://localhost:8761/eureka/}

유레카 클라이언트가 서비스를 등록할 서버 주소를 지정하기 위해 eureka.client.service-url.defaultZone 속성을 사용

@SpringBootApplication
@EnableDiscoveryClient
public class EurekaclientApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaclientApplication.class, args);
    }
}

main 클래스 위에 @EnableDiscoveryClient 어노테이션을 설정하면 완료.

@EnableDiscoveryClient, @EnableEurekaClient 차이점
서비스 디스커버리 라이브러리는 유레카 외에도 주키퍼, 컨설 등이 존재하며 @EnableDiscoveryClient 어노테이션은 모든 라이브러리를 지원하며 @EnableEurekaClient 는 유레카 라이브러리만을 지원한다.

pom.xml이 있는 위치에서 mvn package로 서버 실행가능한 jar파일을 생성하고
2개의 터미널을 열어 각기 다른 포트로 서버를 실행하자.

$ java -jar -DPORT=8081 target/eurekaclient-0.0.1-SNAPSHOT.jar
$ java -jar -DPORT=8082 target/eurekaclient-0.0.1-SNAPSHOT.jar

eureka_registry2

http://localhost:8761/로 접속하면 다음과 같이 2개의 서비스가 등록되어 실행중임을 알 수 있다.

Eureka 클라이언트 종료

유레카 클라이언트를 안전하게 종료하기 위해 actuatorshutdown API를 사용한다.
중단된 이벤트를 다른 유레카 클라이언트가 가로채거나 이벤트르 다시 서버로 보내기 위해 안전한 종료가 필요하다.

pom.xml에 다음 의존성 추가

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

그리고 actuator 관련 속성을 application.properties에 등록한다.

management.endpoint.shutdown.enabled=true
# 보안 해제
management.endpoint.shutdown.sensitive=false
management.endpoints.web.exposure.include=*

출처: https://www.baeldung.com/spring-boot-shutdown

eureka_shutdown

IntelliJ를 통해 생성된 Mapping 정보를 보면 /actuator/shutdown API가 POST방식으로 생성된 것을 알 수 있다.

그이외에도 여러 기능이 추가됨…

REST Client와 같은 툴을 사용해 위 API를 호출하면 다음 메세지를 반환하고 서버가 종료된다.

{"message": "Shutting down, bye..."}

위와 같은 안전한 방식이 아닌 장애나 네트워크 상황으로 인해 서버가 강제 종료될 경우 이미 종료된 서비스가 서버에 계속 남아있는 상황이 발생할 수 있다.

이는 유레카 서버가 특이한 메커니즘으로 클라이언트를 유지하기 때문, 일시적 네트워크 장애로 인한 서비스 해제를 막기위해 보호모드를 동작하는데
이 보호모드 동작시간이 60초가 default 값이다. (속성설정으로 변경 가능)

해당 시간안에 갱신 요청이 일정 횟수 이상 들어오지 않아야 서비스를 해제한다.
다음 설정으로 해제 가능하다.

eureka.server.enable-self-preservation=false

하트비트가 들어오지 않으면 바로 서비스를 제거한다.
물론 좋지않은 설정이며 시간값을 설정후 shutdown 으로 종료해 클라이언트가 유레카 서버에서 서비스를 제거할 수 있도록 하는것이 안정적이다.

이는 변경이 불가능하며 server.servlet.context-path를 통해 context값 변경으로 약같 변경 흉내는 가능하다.