유레카와 통합을 위한 스프링 클라우드 라이브러리 구성
- 서버 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.* 를 접두어로 사용하는 모든 속성을 포함 (아래는 참조 전체 속성목록)
- 클라이언트: 클라이언트가 레지스트리에서 다른 서비스 정보를 얻기 위해 질의하는 방법의 컨피규레이션을 담당 (아래는 참조 전체 속성목록)
- 인스턴스: 포트나 이름 등의 현재 유레카 클라이언트의 행동을 재정의함 (아래는 참조 전체 속성목록)
레지스트리 갱신
= 클라이언트
서버가 종료하여 등록취소 되는데 시간이 오래 걸리는 이유는 모든 클라이언트가 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을 각각 추가해서 변수를 설정해서 분기시키면 편하다.
참고자료
= 서적 - 마스터링 스프링 클라우드 제 4장
'SpringFramework > Spring Cloud (스터디)' 카테고리의 다른 글
Spring Cloud - (6장) 마이크로서비스 간의 커뮤니케이션 (0) | 2022.04.30 |
---|---|
Spring Cloud - (5장) 컨피그를 사용한 분산 컨피규레이션 (0) | 2022.04.17 |
Spring Cloud - (3장) 스프링 클라우드 개요 + 주요 프로젝트 (0) | 2022.04.11 |
Spring Cloud - (1장) 마이크로서비스를 위한 스프링 & 소개 (0) | 2022.04.04 |