본문 바로가기

Spring

[Spring] MSA 프로젝트 만들기 (1)

2023.02.28 - [Server] - [Spring] 마이크로서비스 아키텍쳐 (Micro Service Architecture, MSA)

 

[Spring] 마이크로서비스 아키텍쳐 (Micro Service Architecture, MSA)

이번에 블록체인 기반의 프로젝트를 진행하게 되었는데 팀원들과 MSA 방식으로 프로젝트를 개발해보자는 얘기가 나와서 개발에 들어가기 전에 MSA가 뭔지 모놀리식 방식과는 어떤 차이가 있는지

keylog.tistory.com

이전 글에서 MSA가 뭔지 모놀리스 아키텍처 방식과는 어떤 차이점이 있는지 알아봤는데 이번글에서는 인프런 강의인 Spring Cloud로 개발하는 마이크로서비스 애플리케이션(MSA) 에서 배운 내용으로간단한 MSA 프로젝트를 만들고 마이크로 서비스들 간에 통신하는 방법까지 알아보겠습니다.

Eureka Server

Eureka Server는 넷플릭스에서 스프링 재단에 기부한 OSS Service Registry입이다. 하나의 서버를 사용하면 마이크로 서비스마다 포트번호가 달라지고 여러대의 서버를 사용하는 경우 서비스 주소가 달라지게 됩니다. 그래서 각각의 마이크로 서비스들의 주소값을 Eureka Server에 Key-Value 형태로 등록해 놓고 사용자 요청이 들어왔을 때 조회해서 사용합니다.

Gateway

Gateway는 일종의 Load Balancer로 사용자 요청이 들어왔을때 Eureka Server에서 사용자 요청을 처리할 수 있는 마이크로 서비스의 주소를 조회해와서 요청을 전달해 주는 역할을 합니다. 그 밖에 Gateway에서 처리할 수 있는 일은 다음과 같습니다.

  • 인증 및 권한 부여
  • 서비스 검색 통합
  • 응답 캐싱
  • 정책, 회로 차단기 및 QoS 다시 시도
  • 속도 제한
  • 부하 분산
  • 로깅, 추적, 상관 관계
  • 헤더, 쿼리 문자열 및 청구 변환
  • IP 허용 목록에 추가

Eureka Client

Eureka Client는 해당 프로젝트를 마이크로 서비스로써 사용하겠다는 의미로 Eureka Server에 등록하여 사용합니다. 이번 글에서는 아래와 같이 Eureka ServerAPI Gateway Server를 만들고 User Service, Challenge Service, Payment Service라는 마이크로 서비스를 만들어 보겠습니다.

1.  Eureka Service

먼저 프로젝트를 생성할 때 위와 같이 Eureka Server Dependency를 추가해줍니다. 그런 다음 Eureka Server로 사용하겠다는 의미로 Application 클래스에 아래와 같이 @EnableEurekaServer 어노테이션을 추가해줍니다. 

@SpringBootApplication
@EnableEurekaServer
public class EurekaServiceApplication {

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

}

 

그리고 application.yml 파일을 아래와 같이 작성해줍니다. yml 파일 속성 중 register-with-eureka속성은 현재 프로젝트를 어딘가에 Eureka Client로 등록하겠다는 의미로 디폴트 값이 true입니다. 하지만 현재 프로젝트는 Eureka Client가 아닌 Eureka Server로 사용될 것이므로 false값으로 설정해줍니다.

 

그리고 fetch-registry 속성은 Eureka Server로 부터 인스턴스들의 정보를 주기적으로 가져올 것인지를 설정하는 속성입니다. true로 설정하면 갱신된 정보를 받겠다는 의미입니다.

server:
  port: 8761

spring:
  application:
    name: eurekaservice

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

Eureka Server는 8761 포트가 디폴트 포트로 만약 임의로 변경한다면 아래와 같은 에러가 발생합니다.

 

만약 포트번호를 변경하고 싶다면 eureka.client 속성 하위에 아래 속성을 추가해주면 됩니다.

service-url:
  defaultZone: http://localhost:${server.port}/eureka

2. apigateway-service

다음은 모든 클라이언트의 요청이 지나가고 Load Balancer 역할을 하는 gateway 프로젝트를 생성하겠습니다. 필수 Dependency로 아래 두 가지 Dependency를 추가하여 프로젝트를 생성해줍니다.

그리고 해당 프로젝트를 Eureka Client로 사용하겠다는 의미로 @EnableDiscoveryClient 어노테이션을 추가해줍니다.

@SpringBootApplication
@EnableDiscoveryClient
public class ApigatewayServiceApplication {

    public static void main(String[] args) {
        SpringApplication.run(ApigatewayServiceApplication.class, args);
    }

}

 

다음으로 application.yml 파일을 아래와 같이 작성해 줍니다.

 

server:
  port: 8000

eureka:
  instance:
    prefer-ip-address: true
    instance-id: ${spring.application.name}:${spring.application.instance_id:${server.port}}
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      defaultZone: http://localhost:8761/eureka

spring:
  application:
    name: apigateway-service
  cloud:
    gateway:
      routes:
        - id: user-service
          uri: lb://USER-SERVICE
          predicates:
            - Path=/user-service/welcome
            - Method=GET
          filters:
            - RemoveRequestHeader=Cookie
            - RewritePath=/user-service/(?<segment>.*), /$\{segment}
        - id: user-service
          uri: lb://USER-SERVICE
          predicates:
            - Path=/user-service/welcome/auth
            - Method=GET
          filters:
            - RemoveRequestHeader=Cookie
            - RewritePath=/user-service/(?<segment>.*), /$\{segment}
            - JwtAuthenticationFilter

eureka.instance.prefer-ip-address 속성은 서비스의 호스트 이름이 아닌 IP 주소를 Eureka Server 에 등록하도록 지정하겠다는 의미입니다.

 

Eureka Client  Eureka Server에 등록될 때 자동으로 아래와 같은 조합으로 식별자를 생성하여 등록됩니다.

${spring.cloud.client.hostname}:${spring.application.name}:${spring.application.instance_id:$server.port}}}

 

eureka.instance.instance-id 속성은 위와 같이 자동으로 생성된 식별자를 재정의 하겠다는 속성입니다.

그리고 eureka.client 속성 하위의 service-url 속성은 현재 프로젝트가 등록될 Eureka Server의 위치를 지정하는 속성입니다.

 

spring.cloud.gateway 하위의 속성은 클라이언트로 부터 들어오는 요청의 url에 따라 해당 요청을 처리할 수 있는 마이크로 서비스로 전달하기위한 속성입니다. predicates의 Path값에 해당하는 요청이 들어오면 Eureka Server에 USER-SERVICE라는 이름으로 등록된 마이크로 서비스로 요청을 전달합니다. 그리고 filters 하위에 있는 값은 RequestHeader의 값을 초기화 시키겠다는 속성과 마이크로 서비스에 요청을 전달할 때 요청 url을 user-service/welcome에서 /welcome으로 변경하겠다는 의미입니다.

 

두 번째 필터에 추가된 JwtAuthenticationFilter는 인증 및 권한을 보여하기 위해 스프링 빈으로 등록된 필터를 추가한 것입니다.

3. user-service

마지막으로 user-service 프로젝트를 생성해 보겠습니다. 다른 마이크로 서비스도 같은 방법으로 생성해 주시면 됩니다.

먼저 필수 dependency 로 아래와 같이 Eureka Discovery Client를 추가하여 프로젝트를 생성합니다.

 

그런 다음 gateway 프로젝트와 마찬가지로 @EnableDiscoveryClient 어노테이션을 아래와 같이 추가해줍니다.

 

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class UserServiceApplication {

    public static void main(String[] args) {
        SpringApplication.run(UserServiceApplication.class, args);
    }

}

 

마지막으로 application.yml 파일을 아래와 같이 작성해줍니다. eureka와 관련된 속성은 gateway에서 작성한 yml 파일 속성과 같습니다.

 

server:
  # port 번호가 0번이면 랜덤으로 배정된다.
  port: 0

spring:
  application:
    name: user-service
  h2:
    console:
      enabled: true
      settings:
        web-allow-others: true
      path: /h2-console
  datasource:
    driver-class-name: org.h2.Driver
    url: jdbc:h2:mem:devday
    username: sa
    password:
  jpa:
    hibernate:
      ddl-auto: create
    show-sql: true
    generate-ddl: true

eureka:
  instance:
    prefer-ip-address: true
    instance-id: ${spring.application.name}:${spring.application.instance_id:${random.value}}
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      defaultZone: http://127.0.0.1:8761/eureka

 

위와 같이 프로젝트를 작성하고 Eureka Server를 실행한 후 gateway server와 user-service를 실행해줍니다.

그런 다음 localhost:8761로 접속하면 아래와 같이 apigateway-server와 user-service가 Eureka Server에 등록된 것을 확인할 수 있습니다.

 

다음 글에서는 apigateway-server 에서 JWT 토큰 방식으로 회원인증을 구현하는 방식과 마이크로 서비스 간에 통신하는 방법인 RestTemplate 과 FeignClient에 대해서 알아보겠습니다.