`Spring Cloud로 개발하는 마이크로서비스 애플리케이션 (MSA)` 강의를 듣고 정리한 자료입니다
✨ API Gateway
- 사용자가 설정한 라우팅 설정에 따라서 각각 엔드포인트로 요청 및 응답을 하는 프록시(proxy) 역할을 한다
- 일종의 진입로 역할
- 일괄적으로 처리
✨ 프록시 서버 (proxy server)
정의
- 클라이언트가 자신을 통해서 다른 네트워크 서비스에 간접적으로 접속할 수 있게 해 주는 컴퓨터 시스템이나 응용 프로그램을 가리킨다
프록시 vs 프록시 서버
- 프록시 : 서버와 클라이언트 사이에서 중계기로써 대리로 통신을 수행하는 것 (ex: API Gateway)
- 프록시 서버 : 서버와 클라이언트 사이에서 중계 기능을 하는 것
- 쉽게 말하면 `프록시 서버`는 컴퓨터 시스템이나 응용 프로그램을, `프록시`는 통신 자체를 의미한다 (사실 잘 모르겠어요...)
- 프록시 서버와 게이트웨이는 다른 개념!
- 클라이언트 -> 게이트웨이 -> 서비스
✨ Spring Cloud에서의 MSA 간 통신
1. RestTemplate
- 인스턴스 생성 + 포트번호 & 파라미터
2. Feign Client
- 특정한 인터페이스 생성
- 인터페이스에서 웹으로 따로 호출하고 싶은 추가적인 마이크로서비스의 이름 등록
-> 마이크로서비스의 이름만을 가지고 호출할 수 있게 된다
Ribbon
- Load Balancer 역할 담당
- 비동기 처리 시 문제점을 겪음
- 클라이언트 사이드 내에 있다
Netflix Zuul
- 클라이언트 -> 넷플릭스 Zuul -> 서비스
-> API Gateway와 동일한 역할 수행
=> Netfilx Zuul 실습을 해보자!
✨ Netflix Zuul
1. RestController 추가
- 일반적인 컨트롤러와 REST 컨트롤러의 차이점은 request body와 response body를 구현하느냐, 아니면 제공된 것을 쓰느냐의 차이
cf) RequestMapping : 사용자로부터 요청되는 URI 값을 지정해 놓는 것
2. Zuul 의존성 추가
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
✨ Zuul 관련 설정 오류
Maven 쓰는데 https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-netflix-zuul/2.2.9.RELEASE에 나온 대로 했더니
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>-->
여기에 빨간 줄이 떴다...
해결
<dependencies>
<!-- 이하 생략... -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
</dependencies>
이 밑에
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
이렇게 추가했더니 문제 해결!
✨ Netflix Zuul - Filter 적용
- Zuul 필터 사용을 위해 `ZuulFilter`라는 추상 클래스 상속
-> 컴포넌트 역할로 등록
- 빨간 줄이 뜨는 이유는 추상 클래스인 `ZuulLoggingFilter`에서 해당하는 추상 클래스의 추상 메소드를 적용하지 않았기 때문에 오류가 생김
추상클래스
- 일부 메소드가 구현되지 않고 선언만 되어 있는 클래스
- 일부 클래스의 공통적인 부분을 추출해 어느 정도 규격(틀)을 잡아 놓는 추상적인 클래스
- new (인스턴스화) 불가능 : 객체 생성 X
- 객체 생성이 불가능하다는 점 외 일반 클래스와 별 다를 바 없다
- 인터페이스는 멤버 변수를 갖고 있고, 추상 클래스는 멤버 변수를 갖고 있지 않다
추상 메소드 적용
- 윈도우 기준 `Alt` + `Insert` => Generate -> `Implement Methods...` 클릭 -> 자동 생성
- filterType() : 사전 필터 or 사후 필터
- filterOrder() : 여러 개의 필터가 있는 경우 순서를 의미함
-> 하나만 있는 경우 1 반환
- shouldFilter() : 원하는 옵션에 따라 필터로 사용 여부 지정
- run : 실제 동작 지정
ZuulLoggingFilter
- `@Slf4j` 어노테이션으로 쉽게 log 출력 가능
- 추상 메소드 적용한 모습 (@Override 4개)
package com.example.zuulservice.filter;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
@Slf4j
@Component
public class ZuulLoggingFilter extends ZuulFilter {
@Override
public Object run() throws ZuulException {
log.info("******** printing logs: ");
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
log.info("******** " + request.getRequestURI());
return null;
}
@Override
public String filterType() {
return "pre";
}
@Override
public int filterOrder() {
return 1;
}
@Override
public boolean shouldFilter() {
return true;
}
}
application.yml
server:
port: 8000
spring:
application:
name: my-zuul-service
zuul:
routes:
first-service:
path: /first-service/**
url: http://localhost:8081
second-service:
path: /second-service/**
url: http://localhost:8082
- zuul.routes : 라우터 개개인에 url 등록
- 127.0.0.1:8000/first-service -> path 인식, 8081 포트로 보냄
✨ Spring Cloud Gateway
버전 설정 잊지 말기!
spring boot version : 2.4.1
spring cloud version : 2020.0.0
- 기존 Zuul과 다른 점 : `Netty` 비동기 서버 작동
404 오류 뜨는 이유
- 기존 first-service나 second-service는 `http://localhost:8081/welcome`로 호출을 하는데, `ApigatewayServiceApplication`을 실행시키게 되면 여기서는 `http://localhost:8081/first-service/welcome`로 요청을 받게 되기 때문에 404 오류가 나는 것이다
- 그러므로 `first-service`라는 글자를 가질 수 있게끔 컨트롤러를 바꿔야 한다
API Gateway 사용 시 주의점
- 값이 넘어갈 때 주소값에 있는 것이 포워딩되어 넘어가므로 주소 설정에 주의해야 한다 (맵핑 정보 등록 필요)
✨ Spring Cloud Gateway - Filter
- 동작 : Client -> Gateway -> Predicate -> Pre Filter & Post Filter -> Service
1. Gateway Handler Mapping
- 요청 정보를 받는다
2. Predicate
- 어떤 이름으로 요청되었는지 조건 분기
- application.yml 파일에서 조건절로 쓰임
3. 사전 필터와 사후 필터 분리
- Property 방법과 Java Code 방법이 있다
- Property 방법의 예시로는 yml 파일을 이용해 처리하는 방법이 있다
✨ 필터 처리 방법
1. Java Code 방식
package com.example.apigatewayservice.config;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FilterConfig {
@Bean
public RouteLocator gatewayRoutes(RouteLocatorBuilder builder) {
return builder.routes()
.route(r -> r.path("/first-service/**")
.filters(f -> f.addRequestHeader("first-request", "first-request-header")
.addResponseHeader("first-response", "first-response-header"))
.uri("http://localhost:8081/"))
.route(r -> r.path("/second-service/**")
.filters(f -> f.addRequestHeader("second-request", "second-request-header")
.addResponseHeader("second-response", "second-response-header"))
.uri("http://localhost:8082/"))
.build();
}
}
2. Property (yml 파일) 방식
server:
port: 8000
eureka:
client:
register-with-eureka: false
fetch-registry: false
service-url:
defaultZone: http://localhost:8761/eureka
spring:
application:
name: apigateway-service
cloud:
gateway:
routes:
- id: first-service
uri: http://localhost:8081/
predicates: # ???
- Path=/first-service/**
filters:
- AddRequestHeader=first-request, first-request-header2 # key, value
- AddResponseHeader=first-response, first-response-header2 # key, value
- id: second-service
uri: http://localhost:8082/
predicates: # ???
- Path=/second-service/**
filters:
- AddRequestHeader=second-request, second-request-header2 # key, value
- AddResponseHeader=second-response, second-response-header2 # key, value
✨ 참고 자료
https://www.tibco.com/sites/tibco/files/media_entity/2020-05/api-gateway-diagram.svg
https://ko.wikipedia.org/wiki/%ED%94%84%EB%A1%9D%EC%8B%9C_%EC%84%9C%EB%B2%84
https://velog.io/@im_joonchul/%EC%B6%94%EC%83%81%ED%81%B4%EB%9E%98%EC%8A%A4Abstract-class
https://ggparkitbank.tistory.com/120?category=1015014
'Spring > MSA' 카테고리의 다른 글
[스프링 MSA] MSA_S5 : Catalogs and Orders Microservice (0) | 2023.11.15 |
---|---|
[스프링 MSA] MSA_S4 : Users Microservice (1) (0) | 2023.11.08 |
[스프링 MSA] MSA_S2 : API Gateway Service (2) (0) | 2023.11.01 |
[스프링 MSA] MSA_S1 : Service Discovery (0) | 2023.09.25 |
[스프링 MSA] MSA_S0 : Microservice와 Spring Cloud의 소개 (2) | 2023.09.25 |