[Spring Cloud]Service Discovery 패턴 - MSA 적용기 (1)

HW·2024년 8월 27일
0

MSA

목록 보기
1/4

서론

Monolithic 아키텍처에서 MSA로의 전환을 경험해보고자 개인프로젝트에 Eureka를 적용해봅니다.

본론

MSA 도입 시에 각각의 마이크로 서비스가 확장 / 축소 될 때마다
해당 서비스의 정보 (IP, Port)를 수동으로 업데이트해야하는데
이를 해결하는 것이 Service Discovery 패턴입니다.

Service Discovery 패턴은 Service Registry라는 서비스의 IP, Port 등을 저장 관리하는 주소록을 구현한 것입니다.

이렇게 Service Discovery 패턴을 구현함으로써 분산환경의 서비스가
Service Discovery 구현체에게 서비스의 주소록을 질의함으로써 요청을 전달할 수 있습니다.

Server-Side Discovery / Client-Side Discovery

Service Discovery 패턴에는 2가지 종류가 있습니다.
MSA의 다른 서비스를 호출할 때 Service Registry를 통해서 다른 서비스를 호출하는지 여부에 따라 나뉩니다.

  • Server-Side Discovery : Load Balancer를 통해 다른 서비스 호출
  • Client-Side Discovery : Service Registry를 통해 서비스 호출

Server-Side Discovery

장점

  • 추상화된 Load Balancer만 호출하고, 하위 구현체인 Service Registry는 몰라도 된다.
  • 다른 서비스를 검색하는 로직을 구현할 필요가 없다.
    단점
  • 로드 밸런서를 배치하는 것이 필수적이다.
  • 요청 시 Load Balancer 거쳐야하므로 네트워크 hop 증가로 인한 처리 지연이 된다.

Client-Side Discovery

장점

  • Load Balancer 배치 작업 없이 애플리케이션 코드 단에서 Service Discovery 패턴을 구현할 수 있어 상대적으로 간단하다.
  • 각 서비스를 호출하려는 서비스를 알기 때문에 서비스별로 특성에 맞게 로드밸런싱 구현 가능하다.
    단점
  • 각 서비스별로 다른 서비스를 검색하는 로직을 언어 및 프레임워크 별로 구현해야 한다.
  • Polyglot 환경에서 언어 및 프레임워크별로 여러번 구현해야 한다.

Eureka를 사용한 Client-Side Discovery 구현

다음과 같은 이유로 Client-Side Discovery를 구현합니다.

  • 애플리케이션 코드 단에서 구현 가능하다.
  • 레퍼런스가 많다.
  • 현재 프로젝트는 Java & Spring만 쓴다.

최종적으로 구현해야할 구조는 다음과 같습니다.

  • Eureka Service로 Service Registery 구현
  • 각 마이크로 서비스에서 Eureka Client 라이브러리를 추가하여 Eureka Server에 서스 정보 등록
    • 각 서비스 애플리케이션 실행 시 Eureka Server에 자동으로 서비스 정보 등록
    • 각 서비스에서는 주기적(default: 30초)으로 Eureka Server에게서 다른 서비스들의 정보 업데이트
    • 등록 시 고유ID를 지정하여 서비스 호출 시 IP, Port가 아닌 고유 ID로 서비스 호출

Eureka 구현

Eureka Server 구현

  1. Eureka Server 의존성 추가

    ext {
    	set('springCloudVersion', "2023.0.3")
    }
    
    dependencies {
    	implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-server'
    	implementation 'org.springframework.cloud:spring-cloud-starter-config'
    }
    
    dependencyManagement {
    	imports {
    		mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
    	}
    }
    • eureka-server 의존성을 추가해줍니다.
    • 외부 중앙 설정 서버 (config-service)에서 설정을 가져올 수 있드록 spring-cloud-starter-config 의존성을 추가합니다.
  2. application.properties 설정

    
    server.port=8761
    spring.application.name=discovery
    eureka.instance.hostname=localhost
    eureka.client.register-with-eureka=false
    eureka.client.fetch-registry=false
    eureka.client.service-url.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/
    
    spring.cloud.config.import-check.enabled=false
  3. Eureka Server 활성화

    @SpringBootApplication
    @EnableEurekaServer
    public class EurekaServiceApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(EurekaServiceApplication.class, args);
        }
    
    }

실행 Application 위에 @EnableEurekaServer 어노테이션을 선언합니다.

Eureka Client 구현

  1. Eureka Client 의존성 추가

    ext {
    	set('springCloudVersion', "2023.0.3")
    }
    
    dependencies {
    implementation 'org.springframework.cloud:spring-cloud-starter-config'
    implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    }
    
    dependencyManagement {
    	imports {
    		mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
    	}
    }
    • eureka-client 의존성을 추가해줍니다.
    • 서비스 로직이 구현되는 서버이므로 eureka-client 이외에 필요한 다른 의존성도 추해줍니다.
    • spring-cloud-starter-config는 추후 config-service에서 configuration을 풀링할 수 있도록 하는 의존성입니다.
    • spring-web은 애플리케이션 시작 후 바로 종료 되지 않도록 유지하기 위해 추가합니다.
  2. application.properties 설정

    spring.application.name=user-service
    
    server.port=10001
    eureka.client.register-with-eureka=true
    eureka.client.fetch-registry=true
    eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
  • eureka.client.register-with-eureka : Eureka Server에 자기 자신을 등록할지의 여부

  • eureka.client.fetch-registry : Eureka Server의 등록되어 있는 서비스 캐싱 여부

  • eureka.instance.prefer-ip-address : IP 주소를 Eureka Server에 등록할지 여부 입니다.
    - 기본값은 false, Eureka Server에 각 서비스들이 내부적으로 호스트 이름으로 등록됩니다.
    - 서비스가 배포되는 환경에서 DNS가 존재한다면 호스트 이름을 할당받고 Eureka Server가 잘 등록할 수 있으므로 해당 옵션을 설정할 필요가 없습니다.

  1. Eureka Client 활성화
    ```
    @SpringBootApplication
    @EnableDiscoveryClient
    public class UserServiceApplication {
    
      public static void main(String[] args) {
        SpringApplication.run(UserServiceApplication.class, args);
      }
    
    }
    
    ```
    실행 Application 위에 @EnableDiscoveryClient 어노테이션을 선언합니다.
    그러나 반드시 선언하지 않아도 Eureka Dashboard에 표시 됩니다.

Config Server 구현

  1. Config server 의존성 추가
    dependencies {
    implementation 'org.springframework.cloud:spring-cloud-config-server'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
    }
  2. application.properties 설정
    spring.application.name=config-server
    server.port=8888

Eureka 대시보드 확인

설정했던 애플리케이션을 실행해줍니다.

EurekaService http://localhost:8761 로 접속하면 등록했던 user-service가 보입니다.

결론

Service Discovery 패턴을 구현하기 위해 Eureka를 사용한 Client-Side Discovery 방식을 적용했습니다. 구현된 아키텍처는 다음과 같은 구성요소로 이루어져 있습니다:

  1. Eureka Server: 서비스 레지스트리 역할을 수행하며, 각 마이크로서비스의 정보를 관리합니다.
  2. Eureka Clients: 각 마이크로서비스에 구현되어 Eureka Server에 자신의 정보를 등록하고, 다른 서비스의 정보를 조회합니다.
  3. Config Server: 중앙 집중식 설정 관리를 제공하여 각 마이크로서비스의 설정을 동적으로 관리할 수 있게 합니다.

추후 Config Server의 도입으로 다음과 같은 이점을 얻을 수 있습니다:

  1. 중앙화된 설정 관리: 모든 마이크로서비스의 설정을 한 곳에서 관리할 수 있습니다.
  2. 동적 설정 변경: 런타임 중에 설정을 변경하고 각 서비스에 적용할 수 있습니다.
  3. 환경별 설정 분리: 개발, 테스트, 운영 등 다양한 환경에 대한 설정을 쉽게 관리할 수 있습니다.
  4. 버전 관리: Git과 같은 버전 관리 시스템과 통합하여 설정의 이력을 관리할 수 있습니다.

이러한 구조를 통해 마이크로서비스 아키텍처의 확장성, 유연성, 그리고 관리 용이성을 크게 향상시킬 수 있습니다.
Config Server를 통한 중앙화된 설정 관리는 복잡한 분산 시스템을 효과적으로 운영하고 확장할 수 있습니다.

profile
예술융합형 개발자🎥

0개의 댓글