개발/스프링 MSA

[Spring Cloud로 개발하는 마이크로서비스 애플리케이션(MSA)] Section 1. Service Discovery

용꿀 2023. 8. 8. 01:53

이 글은 인프런 Spring Cloud로 개발하는 마이크로서비스 애플리케이션(MSA) 강의를 들은 후에 정리한 글입니다.
(https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%81%B4%EB%9D%BC%EC%9A%B0%EB%93%9C-%EB%A7%88%EC%9D%B4%ED%81%AC%EB%A1%9C%EC%84%9C%EB%B9%84%EC%8A%A4/dashboard)

 

Spring Cloud로 개발하는 마이크로서비스 애플리케이션(MSA) - 인프런 | 강의

Spring framework의 Spring Cloud 제품군을 이용하여 마이크로서비스 애플리케이션을 개발해 보는 과정입니다. Cloud Native Application으로써의 Spring Cloud를 어떻게 사용하는지, 구성을 어떻게 하는지에 대해

www.inflearn.com

이 글에서 설명되는 내용들은 모두 실제 강의와 다른 Spring Boot 3.1.2 버전입니다.


Spring Cloud Netflix Eureka

Service Discovery: 외부의 서비스들이 Microservice를 검색하기 위해 사용하는 것, 일종의 전화번호부 역할을 함

서비스의 등록과 검색 기능을 제공하는 기능을 Eureka를 사용하여 제공

Eureka Service Discovery - 프로젝트 생성

discoveryservice라는 이름을 가지는 새로운 프로젝트를 생성한다. (Java 17, Spring Boot 3.1.2)

 

application.yml에 다음과 같이 등록한다.

# application.yml
server:
  port: 8761

spring:
  application:
    name: discoveryservice

eureka:
  client:
    register-with-eureka: false
    fetch-registry: false

server:port 속성에서는 Spring Boot 애플리케이션이 실행될 포트를 설정한다. 여기서는 포트 8761에서 애플리케이션이 실행되게 설정을 한 것이다.

spring:application:name 속성은 Spring Boot 애플리케이션의 이름을 설정하는 것으로 여기에서는 "discoveryservice"로 설정한다.

eureka:client는 Eureka Discovery Client의 동작을 구성한다. 이를 통해 애플리케이션이 서비스 검색 및 등록을 위해 Eureka 서버에 자신을 등록할 수 있다.
register-with-eureka: false는 이 서비스가 어떤 Eureka 서버에도 자신을 등록하지 않을 것임을 나타낸다.
fetch-registry: false는 이 서비스가 다른 Eureka 서버로부터 레지스트리 정보를 가져오지 않을 것임을 나타낸다.

 

다음으로 main 함수가 있는 DiscoveryserviceApplication.java에 다음과 같이 어노테이션 하나를 추가한다.

// DiscoveryserviceApplication.java
@SpringBootApplication
@EnableEurekaServer // 추가된 어노테이션
public class DiscoveryserviceApplication {
    public static void main(String[] args) {
        SpringApplication.run(DiscoveryserviceApplication.class, args);
    }
}

@EnableEurekaServer: 이 어노테이션은 해당 애플리케이션이 다른 마이크로서비스들의 등록 및 검색을 관리하는 Eureka Discovery 서버로서 동작하도록 활성화시킨다.

 

실제로 127.0.0.1:8761에 접속해 보면 다음과 같은 실행 화면을 볼 수 있다.

User Service - 프로젝트 생성

user-service라는 이름을 가지는 새로운 프로젝트를 생성한다. (Java 17, Spring Boot 3.1.2)

 

application.yml에 다음과 같이 등록한다.

# application.yml
server:
  port: 9001

spring:
  application:
    name: user-service

eureka:
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      default-zone: http://127.0.0.1:8761/eureka

이전과 달라진 부분만을 설명해 보겠다.


eureka:client는 Eureka Discovery Client의 동작을 구성한다. 이를 통해 애플리케이션이 서비스 검색 및 등록을 위해 Eureka 서버에 자신을 등록할 수 있다.
register-with-eureka: true는 이 클라이언트가 Eureka 서버에 자신을 등록할 것임을 나타낸다.
fetch-registry: true는 이 클라이언트가 Eureka 서버로부터 레지스트리 정보를 가져올 것임을 나타낸다.
service-url 섹션은 Eureka 서버의 URL을 설정한다. 여기서는 기본(default) zone으로 http://127.0.0.1:8761/eureka를 사용하며 이것은 Eureka 서버의 주소를 나타낸다.

 

다음으로 main 함수가 있는 UserServiceApplication.java에 다음과 같이 어노테이션 하나를 추가한다.

// UserServiceApplication.java
@SpringBootApplication
@EnableDiscoveryClient
public class UserServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(UserServiceApplication.class, args);
    }
}

@EnabledDiscoveryClient: 애플리케이션을 서비스 디스커버리 클라이언트로 등록할 때 사용한다.

 

이제 실행 후 유레카 서버에 접속해 보면 아래와 같이 USER-SERVICE가 추가된 것을 확인할 수 있다.

User Service - 등록

위에서 추가된 USER-SERVICE 말고 또 다른 USER-SERVICE를 추가해 볼 것이다.

 

먼저 IntelliJ 우측 상단의 실행 버튼 옆의 클래스 이름을 누르면 내려오는 드롭 다운 선택창에서 Edit Configuration을 클릭한다.

UserServiceApplication을 선택한 상태에서 복사 버튼을 눌러 UserServiceApplication-2를 생성한다.

드롭 다운 선택창을 통해 둘 모두를 실행한다.

그러면 위와 같은 오류창을 보게 될 텐데 이는 9001 포트를 둘 다 사용하려고 하기 때문이다.

Modify options에서 Add VM options 선택하여 다음과 같이 추가하면 UserServiceApplication-2가 9002 포트에서 실행되게 설정할 수 있다.

설정 후 다시 실행하면 아래와 같이 둘 다 정상 작동함을 알 수 있다.

 

또 다른 실행 방법도 사용해 보겠다.

 

IDE의 터미널에서 현재 프로젝트의 경로에 위치한 뒤 다음의 명령어를 입력한다.

mvn spring-boot:run '-Dspring-boot.run.jvmArguments= -Dserver.port=9003'

강의에서의 명령어와 살짝 환경 변수 부분이 다르니 주의하자.

 

실행이 잘 되었는지 브라우저에서 확인해 보면 다음과 같이 잘 실행되었음을 확인할 수 있다.

마지막으로 4번째 인스턴스를 실행해 보자.

cmd에 접속해서 다음 명령어를 입력한다.

mvn clean

mvn compile package

위의 과정을 통해 현재 경로의 target 하위 폴더에 user-service-0.0.1-SNAPSHOT.jar 파일이 생성되었는지 확인 후 아래 명령어를 통해 새로운 인스턴스를 포트 9004에서 실행한다.

java -jar "-Dserver.port=9004" ./target/user-service-0.0.1-SNAPSHOP.jar

브라우저에서 확인해 보면 4개의 인스턴스가 실행 중임을 확인할 수 있다.

이후 정상적으로 모든 인스턴스를 종료한다.

User Service - Load Balancer

지금까지는 포트 번호를 인스턴스를 실행할 때마다 하나하나 지정해 주는 방식으로 진행하였는데, 이는 너무 귀찮은 작업이다.

그래서 랜덤으로 포트 번호를 부여하는 방법을 사용해보고자 한다.

 

application.yml에서 server:port 속성을 기존의 9001에서 0으로 변경한다.

그 이후 실행해 보면 

아래처럼 랜덤으로 지정된 50896 포트에서 실행됨을 알 수 있다.

터미널에서 mvn spring-boot:run 명령을 입력하여 또 다른 랜덤 포트에서 실행되는지 확인해 보자.

51126이라는 랜덤으로 지정된 포트에서 실행됨을 알 수 있다.

 

하지만 브라우저에서 확인해 보면 두 개의 인스턴스가 실행 중인 것으로 나오는 것이 아닌, 하나의 인스턴스만 존재하는 것처럼 보인다. 왜냐하면 application.yml에 지정된 정적인 포트값 그 자체만을 출력해 주는 방식이기 때문이다.

 

이를 해결하기 위해서 application.yml에 새로운 내용을 추가해 주자.

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

새로운 내용을 추가 후 다시 두 인스턴스를 실행하고, 브라우저에서 확인해 보면 아래와 같이 2개의 인스턴스가 나타남을 확인할 수 있다.

위처럼 USER-SERVICE에 대한 자동 포트 부여를 통해 여러 인스턴스를 귀찮게 포트번호를 부여할 필요 없이 생성할 수 있게 됨으로써 편하게 개발자들이 작업할 수 있다.

이렇게 Spring Boot와 Spring Cloud를 사용하여 로드 밸런싱을 쉽게 구현할 수 있다.