[MSA] Service Discovery

Kim Hyen Su·2024년 3월 26일

MSA

목록 보기
3/18
post-thumbnail

0. 들어가기 전

해당 포스팅은 인프런에 "Spring Cloud로 개발하는 마이크로서비스 애플리케이션(MSA)" 강의를 기반으로 작성됐습니다.

포스팅의 모든 사진 자료는 해당 강의 출처임을 밝힙니다.

어제 강의 및 스터디를 진행해보니 혼자 공부할 때보다 조금 더 도움이 된다는 느낌이 강하게 들었습니다 :)

스터디 진행은 다음과 같이 진행되었고 매우 알찼습니다 :))

  • 각자 블로그에 강의를 기반으로 학습한 내용을 이해한대로 정리.
  • 당일 발표자가 자신의 블로그를 기준으로 설명하듯이 발표.
  • 중간에 질문이 있거나 이해가 되지 않았던 부분에 대해서 서로 공유.

마무리까지 잘하면 프로젝트에 큰 도움이 될 수 있을것 같습니다.

오늘은 어제에 이어서 MSA의 각 서비스의 위치 정보를 관리해주는 유레카 서버에 대해서 학습하겠습니다.

📖 학습 목표

  • Eureka 서버에 대한 개념 이해
  • Service Discovery에 대한 이해
  • 프로젝트에 적용 시 필요한 설정

1. Spring Cloud Neflix Eureka

❓ Neflix... 우리가 아는 그 넷플릭스?

네 맞습니다.
Spring Cloud Netflix Eureka는 이름에 있듯이 넷플릭스라는 영상 관련 플랫폼에서 시작된 기술입니다.

넷플릭스에서 스프링 진영에 기부를 하고 이를 발전해나간 형태가 지금의 Spring Cloud Netflix Eureka의 형태입니다.

Spring Cloud Neflix Eureka는 일반적으로 줄여서 ' 유레카 서버(Eureka Server) ' 라고 지칭합니다.

유레카 서버의 대표적인 기능 중 하나가 ' Service Discovery ' 입니다.

다음 그림으로 설명하겠습니다.

클라이언트로부터 들어온 요청을 로드 밸런서에서 받습니다.

로드 밸런서에서 요청을 처리할 서버 인스턴스가 어디있는지 유레카 서버에게 물어봅니다.

유레카 서버는 해당 인스턴스가 등록되어 있는지 확인하고 등록된 경우, 해당 위치 정보를 로드 밸런스에게 알려주게 됩니다.


정리하면,

각 서비스의 위치 정보를 Eureka Server에 저장합니다.

요청 정보가 들어왔을 때, 해당 요청을 처리할 서비스의 위치를 알려줍니다.


2. 실습

실습 환경

위와 같이 spring.io 공식 홈페이지에 3.2.x 버전을 지원한다고 명시돼있습니다.

  • Intelli J

  • Java 17

  • Spring Boot 3.2.4 ver.

  • gradle(강의에서는 Maven 사용)

Eureka Service Discovery - 프로젝트 생성

우선, 마이크로 서비스의 위치정보를 등록하고 관리하기 위한 Eureka Server 부터 생성해보겠습니다.

💡 GroupId, ArtifactId

  • GroupId : 디렉토리명
  • ArtifactId : 애플리케이션명

💡 jar, war

둘 다 자바 애플리케이션을 패키징하는 방식입니다.

  • jar : 독립적인 Java 애플리케이션을 패키징하는 데 적합합니다.
  • war : Java 웹 애플리케이션을 패키징하고 실행하는 데 적합하며, 웹 컨테이너를 함께 패키징합니다.

  • Eureka Server 의존성만 추가.

EcommerceApplication.java

@SpringBootApplication

Spring Boot 내에서 애플리케이션을 실행시키는 클래스에 붙여줍니다.

@EnableEurekaServer

Eureka 서버로 등록. 즉, 해당 서버에서 service discovery 기능을 수행한다는 것을 의미합니다.


application.yml

server.port

유레카 서버는 웹 서비스의 성격을 갖고 있기 때문에 실행을 위해서 포트를 가지고 있어야 합니다.

spring.application.name

마이크로 서비스의 고유 ID를 부여하기 위한 설정입니다. 해당 설정으로 Eureka 서버에서 각 서비스를 구분합니다.

eureka.client.register-with-eureka : false

Eureka server 에게 서비스 자신의 위치정보를 등록하기 위한 설정.

기본값은 true, Eureka 자신의 위치정보를 자신에게 등록하는 것은 의미 없기 때문에 false로 설정했습니다.

eureka.client.fetch-registry = false

Eureka server로 부터 다른 서비스들의 위치 정보를 주기적으로 받아오는 것을 위한 설정.

Eureka 서버에 이미 다른서버의 위치 정보가 있기 때문에 주기적으로 전달받을 필요가 없기 때문에 false로 설정했습니다.

이후 서버 실행 및 http://localhosr:8761/eureka 로 들어가 보시면, 위와 같이 대시보드가 화면에 출력됩니다.

User Service - 프로젝트 생성

그 다음으로, Eureka Server에 등록할 마이크로 서비스(User-Service)를 생성하겠습니다.

  • Eureka Discovery Client 의존을 추가하여 유레카 서버에 위치 정보를 등록할 서비스로 설정합니다.

UserServiceApplication.java

@EnabledDiscoveryClient

Eureka 서버에 주소 등록이 가능하도록 Discovery Client로 활성화함을 의미합니다.

appliction.yml

  • eureka.client.register-with-eureka & fetch-registry 를 true로 설정하여 Eureka Server에 등록 및 다른 서비스 위치 정보를 받아옵니다.

service-url.defaultZone

Eureka Client가 등록될 서버의 위치 주소를 설정합니다.

Eureka server와 User-service 서버를 동시에 수행한 결과 위와 같이 대쉬 보드에 등록된 User-Service를 확인할 수 있습니다.

User Service - 등록

앞서 언급했듯이 MSA의 주요 특징 중 하나인 로드 밸런싱을 위해서는 Eureka Server에서 위치 정보를 얻어와 요청을 분담하여 보내게 됩니다.

이를 위해 User-Service와 동일한 애플리케이션을 하나 복사하여 실행해보겠습니다.

우측 상단 Run/Debug Configuration 설정 - 애플리케이션 복제

User-Service가 실행되고 있는 상태에서 복사한 User-Service-2를 실행하면, 동일한 port 번호로 인해 오류가 발생하게 됩니다.

그렇다면, 이러한 포트 충돌을 해결하기 위해서는 어떻게 해야 할까요?

포트 충돌 방지하기 위한 방법

  1. application.yml 파일 server.port 수정해줍니다.

  2. 위 그림처럼 우측에 설정 스크롤바를 내려 Add VM options를 추가해고, 실행할 인스턴스의 -Dserver.port 속성으로 포트를 수정해줍니다.

  3. 랜덤 포트를 사용합니다.

위 어떤 방식을 사용하든 포트 충돌은 예방할 수 있습니다.

다음과 같이 애플리케이션 2개가 Eureka Server에 등록되어 있는 것을 볼 수 있습니다.

위 1번과 2번 설정은 애플리케이션 복사 시마다 포트를 중복되지 않도록 수정해줘야 한다는 번거로움이 있습니다.

따라서 랜덤 포트를 이용하여 포트 충돌을 해결해보겠습니다.

> 랜덤 포트 사용하기

랜덤 포트 설정은 매우 간단합니다.

다음처럼 application.yml 안에 server.port 설정을 0으로 변경해주면 됩니다.

이제 설정 후 2개의 애플리케이션을 실행해보겠습니다.

결과는 다음과 같습니다.

분명, 서버 상에서는 포트가 다른 2개의 애플리케이션이 각각 실행되었습니다. 하지만, Eureka Server에는 등록되지 않았습니다... Why?!

User Service - Load Balancer

> 정적으로 감지하는 Eureka Server

결론부터 말하면, Eureka Server에서 서비스를 감지할 때 application.yml 파일 내 위치 정보를 정적으로 가져오기 때문입니다.

랜덤 포트 설정은 동적으로 포트번호가 부여됩니다.

따라서, Eureka Server 입장에서는 위치 정보가 똑같은 두 개의 애플리케이션(127.0.0.1:0/user-service)으로 인식하여 하나가 탐지되지 않은 것입니다.

이 문제를 해결하기 위해서는 서비스로부터 생성되는 인스턴스마다 고유한 ID로 구분해줘야 합니다.

> 인스턴스 별 고유한 위치정보 설정

인스턴스 별로 고유한 ID값을 부여하기 위해서는 다음과 같이 설정해주면 됩니다.

application.yml 내 instance id 설정

위 설정을 통해서 모든 인스턴스는 고유한 ID 값이 위치 정보로 설정되는 것입니다.

이제 실행을 해보면 다음과 같이 instance 별로 구분되어 유레카에 등록됩니다.


📜 정리

Eureka Server는 각 서비스의 위치 정보를 저장하고 관리해주는 서버입니다.

위와 같은 기능을 "Service Discovery" 라고 합니다.

부하를 분담하기 위해서 Auto-Scaling이 필요하며 scale-out에 의해 동적으로 생성된 인스턴스에 위치 정보를 부여하기 위해서 위와 같은 과정들이 필요하다고 말할 수 있습니다.

즉, 클라이언트는 인식할 수 없는 상태에서 여러 개의 인스턴스를 생성하고 해당 인스턴스에 위치정보가 Eureka Server에 자동 등록되며, 게이트 웨이 서버에 의해 부하 분산 작업이 수행되는 것이 가능한 것입니다.

위처럼 간단하게 구현했을 뿐인데도 로드 밸런싱이 가능한 기반을 구현할 수 있다는 것이 Spring Cloud의 장점이 아닐까 싶습니다.

profile
백엔드 서버 엔지니어

0개의 댓글