본문 바로가기

SpringFramework/Spring Cloud (스터디)

Spring Cloud - (4장) 서비스 디스커버리

유레카와 통합을 위한 스프링 클라우드 라이브러리 구성

- 서버 API

    - 등록된 서비스 목록 수집을 위한 API

    - 새로운 서비스를 네트워크 위치 주소와 함께 등록하기 위한 API

 

- 클라이언트 API

    - 마이크로서비스 애플리케이션에 의존성을 포함해 사용함

    - 애플리케이션 등록과 등록해제(시작과 종료)를 담당하고, 유레카 서버로부터 주기적으로 최신 서비스 목록을 받아옴

서버측 유레카 서버 실행

- 의존성 추가

    - org.springframework.cloud.spring-cloud-starter-eureka-server

    - (OR) org.springframework.cloud.spring-cloud-starter-netflix-eureka-server

 

- 메인 애플리케이션 클래스에 유레카 서버 활성화 => @EnableEurekaServer

클라이언트 측 유레카 활성화

- 의존성 추가

    - org.springframework.cloud.spring-cloud-starter-eureka

    - (OR) org.springframework.cloud.spring-cloud-starter-netflix-eureka-client

 

- 클라이언트 애플리케이션 메인클래스에 유레카 클라이언트 활성화 => @EnableDiscoveryClient (OR) @EnableEurekaClient

- 유레카 서버는 서비스의 각 인스턴스로부터 heartbeat 메시지를 받고, 설정시간 동안 메시지가 없으면 레지스트리에서 서비스를 삭제함

- 디스커버리 클라이언트는 서버로부터 데이터를 가져와 캐싱하고 주기적으로 변경사항을 점검함

spring:
  application:
    name: client-service
  server:
    port: ${PORT:8081}
  eureka:
    client:
      serviceUrl:
        defaultZone: ${EUREKA_URL:http://localhost:8761/eureka/}
# 같은 jar파일로 인자를 넣어서 각각 클라이언트를 실행
$ java -jar -DPORT=8081 target/sample-client-service-1.0-SNAPSHOT.jar
$ java -jar -DPORT=8082 target/sample-client-service-1.0-SNAPSHOT.jar

클라이언트 인스턴스 종료시 등록 해제

endpoints:
  shutdown:
    enabled: true
      sensitive: false

=> 스프링 actuator의 /shutdown (POST) API로 인스턴스 중단가능. 하지만 실제 운영환경에서는 이렇게 종료되는 경우는 드물며, 실제상황에서는 서버 머신 리붓, 애플리케이션 장애, 서버와 클라이언트간 네트워크 인터페이스 장애 등 예상치 못한 많은 이슈들이 발생한다. 이때 클라이언트가 종료되지 못하고 대시보드에 UP 상태로 나오는 문제가 발생하게 되는데, 이때 eureka.server.enableSelfPreservation을 false로 설정하여 위와같은 문제가 발생하지 않도록 한다.

유레카 클라이언트 API를 사용하는 방법

- com.netflix.discovery.EurekaClient: 유레카 서버가 노출하는 모든 HTTP API를 구현

- org.springframework.cloud.client.discovery.DiscoveryClient: 넷플릭스 EurekaClient를 대체하는 스프링 클라우드의 구현 (디스커버리 클라이언트용으로 사용하는 간단한 범용 API)

고급 컨피규레이션 설정

- 서버: 서버의 행동을 재정의한다. eureka.server.* 를 접두어로 사용하는 모든 속성을 포함 (아래는 참조 전체 속성목록)

=> https://github.com/spring-cloud/spring-cloud-netflix/blob/main/spring-cloud-netflix-eureka-server/src/main/java/org/springframework/cloud/netflix/eureka/server/EurekaServerConfigBean.java

 

- 클라이언트: 클라이언트가 레지스트리에서 다른 서비스 정보를 얻기 위해 질의하는 방법의 컨피규레이션을 담당 (아래는 참조 전체 속성목록)

=> https://github.com/spring-cloud/spring-cloud-netflix/blob/main/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/EurekaClientConfigBean.java

 

- 인스턴스: 포트나 이름 등의 현재 유레카 클라이언트의 행동을 재정의함 (아래는 참조 전체 속성목록)

=> https://github.com/spring-cloud/spring-cloud-netflix/blob/main/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/EurekaInstanceConfigBean.java

레지스트리 갱신

= 클라이언트

서버가 종료하여 등록취소 되는데 시간이 오래 걸리는 이유는 모든 클라이언트가 30초(default)마다 서버로 heartbeat를 보내기 때문. 서버가 heartbeat를 받지 못하면 레지스트리 해제 전 90초를 기다린다. 이 설정을 변경하기위해

- eureka.instance.leaseRenewalIntervalInSeconds # n초마다 서버로 heartbeat를 보냄

- eureka.instance.leaseExpirationDurationInSeconds # heartbeat를 받지 못하는 경우 레지스트리에서 인스턴스를 제거하기 전에 기다리는 n초

 

= 디스커버리 서버

- eureka.server.evictionIntervalTimerInMs # (n 밀리초) 서버가 잘못된 노드를 제거하는 시간 간격 (=하트비트 수신점검)

인스턴스 식별자 변경

기본적으로 모든 인스턴스는 호스트명으로 등록된다.

- eureka.instance.instanceId # 유레카 인스턴스ID 정의

 

하지만 MSA 환경에서는 각 서버마다 DNS가 없는게 일반적이기때문에, IP주소를 사용하면, 조금 더 명확하게 알 수 있을 것이다.

- eureka.instance.preferIpAddress를 true로 설정하면, IP 주소 기반으로 리다이렉션이 된다.

 

- 서비스의 네트워크 위치 결정을 위한 방법으로 IP사용 시 문제가 발생할 수 있다. 하나의 서버머신에 두개 이상 네트워크 인터페이스가 있는 경우이다. (예) 사내망, 외부망) 다른 IP 접두사를 갖는 두개 이상의 네트워크 인터페이스를 갖게 되는데, 이경우에 yml파일에 아래처럼 설정하여 해결할 수 있다.

  spring:
    cloud: 
      inetutils:
        ignoredInterfaces: # 무시할 패턴
          - eth1*

  spring:
    cloud: 
      inetutils:
        preferredNetworks: # 선호하는 네트워크 주소를 정의
          - 192.168

응답캐시

- 유레카 서버는 클라이언트 응답을 캐싱하고 30초마다 무효화한다. /eureka/apps API를 호출해 확인할 수 있다. 클라이언트 애플리케이션 등록 후 바로 호출 시 응답에 나타나지 않는 이유임. 30초 후 재시도 하면 나옴. 응답캐시 타임아웃은

eureka.server.responseCacheUpdateIntervalMs (# (n 밀리초) 유레카 서버의 캐시 업데이트 시간 간격)속성으로 설정가능하다.

- 유레카 클라이언트도 유레카 레지스트리를 캐싱한다. 30초마다 백그라운드 task로 비동기 갱신진행. eureka.client.registryFetchIntervalSeconds (# 유레카 클라이언트의 레지스트리를 받아오는 주기 시간설정) 속성으로 변경 가능하다.

 

(!) 클라이언트와 서버 간의 보안 통신 관련 내용은 이후 책의 12장에서 다루므로, 여기에서는 생략할 것이다.

실습

 

JangYunSang / ys-spring-cloud

스프링 클라우드 스터디

gitlab.com

(스프링부트 2.6.X 버전대로 세팅하여 진행. 컨피규레이션 속성값들이 camelCase에서 kebab-case로 변경된 부분이 있다.)

참고할 부분

- eureka : 유레카 디스커버리 서버

- eureka.client : 유레카 클라이언트

 

(!) 여러개의 서비스를 실행시키는 경우

jar파일을 build하여 실행시키면 된다. (매우 귀찮더라 ㅠㅠ)

테스트가 목적이라면, IDE에 아래와 같이 run application을 각각 추가해서 변수를 설정해서 분기시키면 편하다.

본인은 yml파일에 spring.config.activete.on-profile 값으로 맞춰서 설정했다

 

run application 여러개! (java -jar와 같은효과..)

참고자료

= 서적 - 마스터링 스프링 클라우드 제 4장

= https://github.com/eva-seulki/spring-cloud-study/wiki/04.-%EC%84%9C%EB%B9%84%EC%8A%A4-%EB%94%94%EC%8A%A4%EC%BB%A4%EB%B2%84%EB%A6%AC