유레카와 통합을 위한 스프링 클라우드 라이브러리 구성
- 서버 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장에서 다루므로, 여기에서는 생략할 것이다.
실습
(스프링부트 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 |