[MSA] Authentication System 개발기(2) - Service Registry와 Gateway

나르·2021년 12월 23일
2

Architecture

목록 보기
3/6
post-thumbnail

1. Eureka (Service Registry)

1.1. Eureka란?

Eureka는 넷플릭스에서 공개한 Service Registry, REST 기반의 미들웨어 서버입니다.
마이크로 서비스를 하다보면 내부 서비스들끼리 통신을 할 경우가 발생합니다.
A서버에서 B서버로 요청할 때 IP주소로 요청을 하게 된다면 B의 IP가 변경되었을 때 A에 있는 B의 IP 정보도 수정해야 합니다.
이러한 불편을 해소하기 위해 Service Registry에 IP, Port, AppName, instanceID 등 서버 정보를 등록해두면, 각각의 서버는 Service Registry 에 등록되어 있는 서비스 이름으로 호출할 수 있게 됩니다.

1.2. Eureka Server

Eureka 서버를 사용하기위해 다음 의존성을 추가해줍니다.
선택적으로 보안을 위한 security나, 모니터링을 위한 actuator 등을 추가할 수도 있습니다.

build.gradle

implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-server'

유레카 서버를 활성화하기 위해 어플리케이션에 @EnableEurekaServer 어노테이션을 추가해줍니다.
app.java

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

설정파일에서 기본 정보를 입력해줍니다.
application.yml

eureka:
  client:
    register-with-eureka: false
    fetch-registry: false
server:
  port: 8761
  • register-with-eureka : eureka에 등록 여부를 정합니다. 이 서버는 본인 자신이기에 등록하지 않습니다.
  • fetch-registry : registry의 항목을 로컬로 캐시할것인지 정합니다. 이것도 필요 없으므로 하지 않습니다.

완료 후 서버를 실행하면 eureka가 활성화 된 것을 알 수 있습니다.

http://localhost:8761

1.3. Eureka Client

서비스를 eureka에 등록하기 위해 다음 의존성을 추가합니다.

build.gradle

implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'

유레카 클라이언트를 활성화하기 위해 어플리케이션에 @EnableDiscoveryClient 어노테이션을 추가해줍니다.

@EnableEurekaClient vs. @EnableDiscoveryClient
EnableDiscoveryClient는 spring-cloud-commons 기반으로 유레카 이외에 consul, zookeeper들이 구현되어있습니다. EnableEurekaClient는 spring-cloud-netflix에 기반을 두고 있으며, 유레카 관련만 의존해 있습니다.
Eureka 기반으로 구성한다면 EnableEurekaClient로 충분하고, 그 외에는 EnableDiscoveryClient를 사용하면 됩니다.

app.java

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

설정파일에서 기본 정보를 입력해줍니다.
application.yml

# Eureka
eureka:
  client:
    service-url:
      defaultZone: http://localhost:{eureka port}/eureka/
    fetch-registry: true
    register-with-eureka: true
spring:
  application:
    name: AUTH-USER-SERVER
server:
  port: 10030

이제 서버를 실행하면 유레카에 다음과 같이 설정한 이름으로 인스턴스가 등록된 것을 볼 수 있습니다.

2. Gateway 연동

2.1. Zuul vs. SCG(Spring Cloud Gateway)

Spring Cloud의 초창기 버전에서는 Netfilx OSS(Open Source Software)에 포함된 컴포넌트인 Zuul 을 사용했습니다. (이렇게 Spring Cloud + Zuul의 형태를 Spring Cloud Zuul이라고 합니다.) Zuul은 서블릿 프레임워크 기반으로 만들어졌기 때문에 동기(Synchronous), 블로킹(Blocking) 방식으로 서비스를 처리했었고, Zuul2로 업그레이드 하게 되며 비동기(Asynchronous), 논블로킹(Non-Blocking) 방식을 지원하게 되었습니다.

하지만 Zuul은 Spring Eco 시스템의 취지와 맞지 않아, Spring Cloud Gateway에서는 Zuul2를 사용하지 않고 Spring Cloud의 공식 API Gateway 프로젝트인 Spring Cloud Gateway를 개발하게 됩니다.
Netflix Zuul 과 같은 기능을 수행하지만 비동기 수행을 위해 Spring WebFlux + Netty 런타임 기반으로 돌아가기 때문에 서블릿 컨테이너나 WAR로 빌드된 경우 동작하지 않습니다.

2.2. gateway 의 역할

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

2.3. 의존성 추가

implementation("org.springframework.cloud:spring-cloud-starter-gateway")

2.4. application.yml 설정 등록

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/
    register-with-eureka: true
    fetch-registry: true
spring:
  application:
    name: AUTH-GATEWAY-SERVER
  cloud:
    gateway:
      routes:
        - id: AUTH-AUTH-SERVER
          uri: lb://AUTH-AUTH-SERVER
          predicates:
            - Path=/api/v1/auth/**
          filters:
            - RewritePath=/api/v1/auth/(?<path>.*),/$\{path}
        - id: AUTH-USER-SERVER
          uri: lb://AUTH-USER-SERVER
          predicates:
            - Path=/api/v1/user/**
          filters:
            - RewritePath=/api/v1/user/(?<path>.*),/$\{path}
  • id: 해당 라우트의 고유 식별자를 나타냅니다.
  • uri: 해당 라우터의 주소를 나타냅니다. gateway를 eureka의 client 로 지정하면 eurek에 등록된 인스턴스명으로 설정이 가능합니다
  • predicates: 해당 라우터의 조건부를 작성, /user/**으로 시작하는 요청의 경우 해당 라우터로 요청을 보냄
  • filters: 해당 라우터의 필터로, RewritePath는 강제로 Path를 다시 작성합니다. 이는 연결된 api의 prefix를 대신하기때문에 RewritePath를 지정하면 서비스 request mapping에서 prefix를 지워줘야합니다.

built-in Predicate Factory를 이용한 라우터 조작

SCG에는 path 외에도 여러 Predicates를 제공합니다.
After, Before, Between 는 시간과 관련된 Predicates로, 말 그대로 특정 시간 이후, 특정 시간 이전, 특정 시간 사이를 의미합니다. 날짜 관련 매개변수는 ZonedDateTime 형식을 사용합니다.

predicates:
    - Path=/api/v1/auth/**
    - After=2021-12-23T19:25:19.126+09:00[Asia/Seoul]
...
predicates:
    - Path=/api/v1/auth/**
    - Between=2021-12-23T19:25:19.126+09:00[Asia/Seoul],2021-12-31T19:25:19.126+09:00[Asia/Seoul]

Cookie 는 요청에 Cookie 값이 지정된 정규표현식을 만족하는지 확인합니다.

- Cookie=valid, naver

Method 는 HTTP Method 가 일치하는지 확인합니다.

- Method=POST

Reference

https://sabarada.tistory.com/62
https://happyer16.tistory.com/entry/Eureka-Server%EB%9E%80
https://kobumddaring.tistory.com/44
https://cheese10yun.github.io/spring-cloud-gateway/
https://www.slideshare.net/ifkakao/msa-api-gateway
https://otrodevym.tistory.com/entry/spring-boot-%EC%84%A4%EC%A0%95%ED%95%98%EA%B8%B0-20-spring-cloud-gateway1-%EC%84%A4%EC%A0%95-%EB%B0%8F-%ED%85%8C%EC%8A%A4%ED%8A%B8-%EC%86%8C%EC%8A%A4
https://tmdrl5779.tistory.com/182?category=875847
Spring Cloud 공식문서

profile
💻 + ☕ = </>

0개의 댓글