API Gateway 라는 것은, Reverse Proxy처럼 클라이언트 요청의 앞단에 위치한다.
마치 ‘도어 맨' 역할처럼 들어온 요청들에게 어디로 가야할 지 ‘라우팅’해줄 수 있고 들어오고 나가는 명단을 ‘로깅’할 수도 있다.
구체적으로는 다음과 같은 역할들이 있다.
API 라우팅
인증 및 권한 부여
속도 제한
부하 분산 (로드밸런싱)
로깅 (모니터링)
오케스트레이션
등...
스프링 클라우드 게이트웨이도 위에서 언급한 API 게이트웨이 중 하나다.
다시 말해, Spring Reactive 환경에 구현된 API Gateway다.
API 게이트웨이의 구현체로는 SCG를 제외하고도 Zuul과 Amazon API가 있다.
다만, 차이점에서 볼 수 있는 것처럼 SCG는 비동기 처리에 유리한 반면 Zuul은 그렇지 않다.
때문에 더 이상 Zuul을 지원하지 않고 Spring.io 는 SCG를 권장한다.
위의 사진을 통해 SCG 구조를 간단히 확인할 수 있다.
📌 Route
응답을 보낼 목적지 uri와 필터 항목을 식별하기 위한 ID로 구성되어 있고 라우팅 목적지를 의미한다.
📌 Predicate
요청을 처리하기 전 HTTP 요청이 정의된 조건에 부합하는지 검사하며 Java 8의 Function Predicate 이다.
📌 Filter
게이트웨이에서 받은 요청과 응답을 수정하는 역할로 Spring Framework의 WebFilter 인스턴스이다.
# application.yml 예시
spring:
cloud:
gateway:
default-filters:
- name: GlobalFilter
agrs:
preLogger: true
postLogger: true
routes:
- id: product-service
uri: lb://PRODUCT-SERVICE
predicates:
- Path=/product/**
filters:
- name: UserFilter
args:
baseMessage: productFilter
preLogger: true
postLogger: true
필터는 이외에도 튜닝할 수 있는 옵션(클래스 선언 등)이 다양한데, 각각에 대한 상세 정보는 외울 순 없으므로 필요시에 찾아보는 것이 좋다.
다만, 구성이 디폴트로 적용되는 GlobalFilter와 각 서비스에 적용할 수 있는 내부 ServiceFilter로 구성된다는 것은 알아야한다.
실제 로그를 보면 글로벌 필터 다음으로 서비스 필터가 찍힌다. (순서)
이러한 SCG의 내부 요청 흐름을 그림으로 보면 아래와 같다.
위에서 본 application.yml 예시 파일과 같이 작성하고
build.gradle 또는 pom.xml 에 아래의 의존성을 주입하면 SCG 구현은 간단히 끝난다.
implementation 'org.springframework.cloud:spring-cloud-starter-gateway'
우리는 그냥 Spring Cloud Gateway를 구현하려는 것은 아니고 이를 MSA에 적용하려는 것이기 때문에 Eureka와 병행되어야 한다.
유레카만 구현된 서비스는 아래의 모습과 같다.
여기에 스프링 클라우드 게이트웨이를 붙이면 아래의 모습이 된다.
이를 바탕으로 클라이언트 요청 시나리오를 보면 다음과 같다.
유레카 서버는 실행한 상태라고 가정.
각 인스턴스(서비스)를 실행하여 유레카 서버에 등록
클라이언트에서 로그인 요청이 SCG로 들어온다.
게이트웨이가 받은 요청을 어떤 서비스에서 해결할 지 디스커버리(유레카)에게 찾는다.
유레카가 응답해준다.
게이트웨이는 받았던 로그인 요청을 Auth 서비스에게 던진다.
최종 결과를 사용자에게 리턴한다.
API 게이트웨이 또한 유레카 입장에서는 서비스 중의 하나다.
때문에 Eureka client 설정 코드를 그대로 추가하여 Eureka 서버에 등록해주면 된다.
유레카 설정을 끝내고 실행해보면 위처럼 ui 상에서 좌측 하단에 Gateway-service가 등록된 걸 볼 수 있다.
GitHub - https://github.com/SheepEatLion/eureka_server.git ← 유레카 서버
GitHub - https://github.com/SheepEatLion/msa-spring-cloud-gateway.git ← 스프링 클라우드 게이트웨이 [9000port]
GitHub - https://github.com/SheepEatLion/msa-product-service.git ← 상품 서비스 [8080port]
GitHub - https://github.com/SheepEatLion/msa-shop-service.git ← 주문 서비스 [8081port]
깃허브에 실습용으로 간단하게 상품서비스와 주문서비스를 제작해서 Spring Cloud Gateway 및 Eureka와 Feign client 등을 적용시켜 뒀으니 클론해서 실행시켜 보면 더 자세히 알 수 있다.
모두 실행한 뒤, 포스트맨 또는 스웨거를 통해 테스트할 수 있도록 구성해두었다.
게이트웨이만 있으면 yml 설정에서 아래처럼 http 주소를 적어야되는데
#게이트웨이만 있을 경우 예시 코드
routes:
- id: user-service
uri: http://localhost:64412
predicates:
- Path=/user/**
유레카가 있으면 게이트웨이에 로드밸런싱을 적용할 수 있다.
routes:
- id: user-service
uri: lb://USER-SERVICE
predicates:
- Path=/user/**
uri 의 lb 는 Load Balancing 의 약자이며, 유레카에 등록된 서비스명으로 탐색하는 형식.
spring:
cloud:
gateway:
globalcors:
corsConfigurations:
'[/**]':
allowedOrigins: "*"
allow-credentials: false
allowedHeaders: "*"
allowedMethods: "*"
헤더에 multi-value 작업을 할 경우, 아래처럼 필터 한 줄을 더 추가해야 문제가 없다.
spring:
cloud:
gateway:
default-filters:
- DedupeResponseHeader=Access-Control-Allow-Origin Access-Control-Allow-Credentials, RETAIN_UNIQUE
globalcors:
corsConfigurations:
'[/**]':
allowedOrigins: "https://localhost:8089"
allow-credentials: true
allowedHeaders: "*"
allowedMethods: "*"
이 외에도 토큰 등의 인증 관련해서는 따로 작성할 예정이다.
SCG는 게이트웨이를 이해하고 있다면 개념은 간단하고, 비동기가 적용된 API 게이트웨이로 요약할 수 있다.
cloud gateway git repo에 먼가 소스나 config 파일들이 업데이트 되지 않는것 같습니다!!
설명 잘볼고갑니다 ~