MSA 6일차 - Chap03. 디스커버리 서버와 유레카

Kim Hyen Su·2023년 10월 17일
0
post-custom-banner

3. 스프링 디스커버리 유레카 서버

스프링 클라우드에서 제공하는 Eureka는 마이크로서비스 아키텍처에서 서비스의 등록, 발견, 및 관리를 위한 서비스 디스커버리 서버이다. 이를 통해 마이크로서비스 간의 통신이 효율적으로 이뤄질 수 있다.

우선 설명하기에 앞서, Spring-cloud Eureka란 무엇일까?

스프링 클라우드에서 제공한 API를 참고하여 각 기업마다 구현한 코드로써, Open source의 이점을 활용하기 위해 Spring Cloud에 기부한 구현 코드이다.

그 중 하나가 Spring-cloud Eureka이다.

Eureka는 2가지로 분류되는데, Eureka Server와 Eureka Discovery Client로 구분된다.

  • Eureka Server : 디스커버리 서버로서, 로드 밸런싱과 헬스 체크 기능을 한다.
  • Eureka Discovery Client : 유레카 서버로 부터 관리될 마이크로서비스들을 의미한다.

디스커버리 서버가 필요한 이유?

img

게이트웨이 서버로만 사용할 경우, 로드 밸런싱이나 헬스 체크까지 하는데 어려움이 있어, 이를 할당한 디스커버리 서버로 로드 밸런싱 및 헬스 체크 기능을 수행하도록 한다.

🎇 Spring cloud Eureka

주요 특징 :

  • 서비스 등록(Service Registration) : 마이크로서비스 시작 시 Eureka 서버에 자신의 위치 정보를 등록한다. 이를 통해 다른 서비스나 클라이언트가 해당 서비스를 찾을 수 있다.
  • 서비스 감지(Service Discovery) : Eureka 클라이언트 라이브러리를 사용하여, 서비스를 찾고 해당 서비스의 메타데이터를 가져올 수 있다. 이를 통해 동적으로 서비스의 위치 파악이 가능하다.
  • 서비스 상태 감시(Health Monitoring) : Eureka는 주기적으로 등록된 서비스의 상태를 확인한다. 이를 통해 장애가 발생한 서비스를 감지하고 다른 서비스로 요청을 라우팅할 수 있다.
  • 동적 서비스 변경(Dynamic Service Changes) : 새로운 서비스 인스턴스가 추가되거나 기존의 인스턴스가 제거되어도 Eureka는 이를 감지하고 서비스 목록을 업데이트한다.
  • 클라이언트 사이드 로드 밸런싱(Client-Side Load Balancing) : 유레카 클라이언트 라이브러리는 여러 인스턴스 중 하나를 선택하여 서비스로 요청을 보내는데, 이를 통해 부하를 분산한다.

작동 원리 :

  1. Eureka 서버 구동 : 마이크로서비스에서 사용할 Eureka 서버를 실행. 이는 서비스 디스커버리의 중심 역할을 한다.
  2. 서비스 등록 : 마이크로서비스가 시작될 때, 해당 서비스는 Eureka 서버에 자신의 정보를 등록한다. 이 정보에는 서비스의 이름, IP 주소, 포트 번호 등의 정보가 포함된다.
  3. 서비스 감지 : 다른 마이크로서비스나 클라이언트가 특정 서비스를 호출하기 위해서는 Eureka 클라이언트 라이브러리를 사용하여 Eureka 서버에서 해당 서비스의 인스턴스를 찾아야 한다.
  4. 서비스 사용 : 클라이언트는 Eureka로부터 받은 서비스 인스턴스 목록 중 하나를 선택하여 요청을 보낸다. 이때, 클라이언트 사이드 로드 밸런싱을 통해 부하가 고르게 분산된다.
  5. 서비스 상태 감시 : Eureka 서버는 주기적으로 등록된 서비스의 상태를 확인한다. 만약 서비스가 응답하지 않는다면 해당 인스턴스를 다른 인스턴스로 대체할 수 있다.
  6. 동적 서비스 변경 : 새로운 서비스 인스턴스가 추가되거나 기존 인스턴스가 제거되면, Eureka는 이를 감지하고 서비스 목록을 업데이트한다.

Eureka 서버 설정 :

server : 
	port : 8761
eureka: 
	client:
		register-with-eureka: false
		fetch-registry: false

위 설정은 Eureka 서버를 8761 포트로 실행하며, 서비스 등록 및 서비스 목록 조회를 위한 설정이다.

register-with-eureka, fetch-registry 를 false로 설정하여 해당 서버는 자신을 등록하지 않고, 등록된 서비스 목록을 가져오지 않도록 설정했다.

요약 :

Spring cloud Eureka는 서비스 디스커버리를 쉽게 구현할 수 있도록 해주는 라이브러리이다. 서비스 등록, 감지, 상태 모니터링 등을 통해 마이크로서비스 간의 효율적인 통신을 가능하도록 해준다.

실습하기

프로젝트 생성 시 디스커버리 유레카 서버를 추가해준다.

유레카 실습1

그 다음으로 ServerApplication 에 @EnableEurekaServer 어노테이션을 추가해준다.

유레카 실습2

마지막으로, application.yml 파일에 discovery-server 관련 설정을 추가해준다.

유레카 실습3

Eureka 서버에 서비스 등록하고 확인하기

유레카 서버에 등록할 서비스는 Eureka Discovery Client 의존성을 추가해줘야 한다.

유레카 클라이언트 실습1

생성된 프로젝트 ServiceApplication 클래스에 @EnableDiscoveryClient 어노테이션을 추가해준다.

유레카 클라이언트 실습2

위 어노테이션이 추가돼야 유레카 서버에서 클라이언트로 인식되며 통신이 가능해진다.

application.yml 파일에 마이크로서비스 포트번호와 마이크로서비스 명칭을 추가해준다.

유레카 클라이언트 실습3

클라이언트를 유레카 서버에 등록해준다.

유레카 서버 클라이언트 추가

  • 등록 전 유레카 대시보드

유레카 대시보드1

  • 등록 후 유레카 대시보드

유레카 대시보드2

동일 프로젝트로 서버 2개 이상 실행시키기

실제 빌드 파일을 2개 이상 실행시켜도 되지만, 하나의 인텔리제이에서 여러 개의 서비스 인스턴스를 실행 해보자.

서비스 추가1

먼저 위 그림에서 처럼 Edit Configuration으로 이동한다.

서비스 추가2

위처럼 왼쪽에서 3번째 복사 버튼을 눌러준 뒤 apply 버튼을 통해 적용해준다.

img

복사 후 실행 탭을 다시 보면 이제 2개의 선택지가 있는것을 확인할 수 있다.

위의 복사된 인스턴스를 추가로 실행 시키면,

img

위처럼 포트 충돌로 인해 실행이 되지 않는다.

이는 본래 인스턴스에서 8003번 포트를 사용 중이기 때문이다.

이를 해결하기 위해서는

  1. 서버 실행 단계에서 포트값을 새롭게 지정한다.
  2. 각 서버 실행 시마다 랜덤포트를 실행하도록 한다.

라는 해결책이 있다.

우선, 1번 부터 확인해보면

  • application.yml 파일에서 port 번호 수정.
  • Edit Configuration - add VM Options 에서 추가.

위 두가지 방법이 있는데, 일일히 yml 파일에서 port 번호를 수정해주는 것은 번거롭고, 확인하기 어렵기 때문에

Edit Configuration에서 인스턴스 생성 시 add VM Options로 포트를 추가해주도록 설정한다.

img

Add VM options 클릭.

img

-Dserver.port=포트번호 를 입력해준다.

위에서 -D는 detach 모드를 의미하며, 콘솔창을 숨기고 애플리케이션을 가동한다는 의미이다.

RUN이 없다

이는 인텔리제이 콘솔창이 하나이기 때문에, 두 개 이상을 하나의 인텔리제이에서 기동 시 콘솔창을 숨겨줘야 한다.

실제 Eureka 서버 대시보드에 아래처럼 추가된다.

추가됨!

포트번호를 매번 인스턴스 생성 시마다 부여하는 것도 의미는 있다.

하지만, 인스턴스 갯수가 커질수록 이를 수동으로 별도 지정하는 것은 오류가 날 확률이 높아진다.

따라서, 2번 방법으로 포트를 추가해주는 것이 더 합리적이다.

0으로 수정

위의 방식대로 하기 위해서 먼저 server.port=0으로 수정해준다.

0번 포트는 실제로 없는 포트이기 때문에 사실상 랜덤포트를 배정하라는 의미가 된다.

삭제

복사한 인스턴스에 추가했던 포트번호 추가 설정을 지워준다.

이제 실행하면 아래처럼 포트번호가 랜덤하게 배정된다.

2번 포트번호 여러개 지정

하지만,

img

실제 충돌은 없지만 실행하는 2개의 인스턴스가 명목상 0번 포트로 감지되어

위처럼 1개의 인스턴스만 실행되는 것으로 나온다.

따라서 각 인스턴스 마다 유레카에 보여지는 이름을 다르게 설정할 필요가 있다.

application.yml
eureka:
  instance:
    instance-id: ${spring.client.cloud.hostname}:${spring.application.instance_id:${random.value}}

위처럼 yml 파일에 설정을 추가해준다.

이후 모든 서비스 인스턴스를 재실행 해주면, 포트번호를 직접 지정하지 않고도 식별된 인스턴스를 감지할 수 있더록 되었다.

img

기존에 있던 서비스에 Eureka Client 적용하기

기존에 first-service 와 second-service를 활용

프로젝트 생성 시점이 아닌 이미 완성된 프로젝트 디스커버리 클라이언트 등록을 위해 아래와 같은 과정으로 진행해주면 된다.

  1. mvnrepository.com 에서 eureka client를 검색

img

위의 Eureka Client 의존성을 build.gradle에 추가해준다.

  1. application.yml 파일에 client 관련 설정을 추가해준다.
application.yml
eureka:
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      defaultZone: http://127.0.0.1:8761/eureka
  instance:
    instance-id: ${spring.application.name}:${spring.application.instance_id:${random.value}}
  1. ServerApplication에 @EnableDiscoveryClient 어노테이션을 추가해준다.

로드밸런서 활용하기

먼저 gateway-server 역시 유레카에서 사용할 수 있도록 등록.

Sping Cloud Gateway에서 이제 uri를 변경해야 한다.

img

유레카에 등록된 이름을 그대로

lb:// 유레카 등록어플리케이션명

형식으로 변경하여 uri에 등록해주면 된다.

그 다음 포트번호를 0으로 바꿔서 랜덤포트를 활성화 시켜준 다음

컨트롤러 측에 포트번호를 보여주는 기능을 구현한다.

이렇게 되면 로드 밸런서가 어떤 서비스가 보내주는지에 따라

그때 그때 보여지는 포트번호가 달라질 것이다.

일단 유레카 서버에서 상태창에서 보여지는 이름을 어플리케이션명으로 바꾸기 위해

eureka:
  instance:
    instance-id: ${spring.application.name}:${spring.application.instance_id:${random.value}}

위 처럼 인스턴스 아이디를 ${spring.application.name} 으로 변경해준다.

img

그 다음으로 컨트롤러 쪽에서 포트번호를 감지할 수 있는 멤버변수를 추가해보겠다.

img

간헐적으로 서버를 재시작하면 아래와 같이 Down이라고 현재 내려가고 있는 서버 목록이 나타나는 경우가 있다.

유레카 디스커버리 서버는 클라이언트와 30초 동안 3번 통신한 후 헬스체크를 종료하기 때문에

간헐적으로 저렇게 나올 수 있지만 결국 자동으로 해결되므로 걱정하지 않아도 된다.

게이트웨이를 경유하여 port-check를 해보자

img

img

위처럼 포트 번호를 바꿔가면서 접속시켜주어 로드 밸런싱이 일어나는 것을 볼 수 있다.

profile
백엔드 서버 엔지니어
post-custom-banner

0개의 댓글