[SpringCloud] API Gateway + Filter(+커스텀필터,글로벌필터,로깅필터)

Hannana·2024년 12월 14일

서버 분산했으니 이제 클라이언트 단에서,
직접 서비스를 호출하지 않고 각각의 마이크로서비스로 요청되는 모든 정보에 대해 일괄 처리할 수 있는 프록시 역할이 필요하다.(로드밸런서)

  • 처음 진입점 - 중간 단계 ... --> 추적 가능
  • 방화벽 역할(얘 통해서만 들어와)

등등

MSA간 통신

1) RestTemplate
2) Feign Client(스프링클라우드 라이브러리)
-MSA이름으로 호출 가능

Gateway 서비스

-Ribborn 서비스
: 클라이언트 측에 설정해놓고(client-side) 마이크로서비스 호출.
그러나 이건 동기식 서비스.. 업데이트 더이상 안됨

-Netflix Zuul
: 클라이언트가 넷플릭스 줄에 연결하면 얘가 서버에 던져줄 것. 역시나 업데이트 더이상 안된다.

-Spring Cloud Gateway(대체)
: 비동기 서비스 호출 가능

Spring Cloud Gateway

  • 8081,8082 서버 돌리고 api호출 확인

  • 방법1) yaml에 게이트웨이 서버 추가(decovery-(gateway)-service)
spring:
  application:
    name: gateway-service
  cloud:
    gateway:
      mvc:
        routes:
          - id: first-service #when the service comes in,
            uri: http://localhost:8081/ #allocate it at this port
            predicates:
              - Path=/first-service/**
          - id: second-service
            uri: http://localhost:8082/
            predicates:
              - Path=/second-service/**
server:
  port: 9000
eureka:
  client:
    register-with-eureka: false
    fetch-registry: false
    service-url:
      defaultZone: http://localhost:8761/eureka

-포트는 9000번, 유레카 서버와 연결
-/first-service로 시작하는 클라이언트 요청이 들어오면, 8081 포트로 바인딩한다.

  • 방법2) Filter 적용
    -@Configuration : 프로젝트 시작 시, 메모리에 먼저 등록
    apigateway에 cofig 형태로 필터를 등록해주자.
@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();
    }

=> yaml파일 대체

@GetMapping("/message")
    public String message(@RequestHeader("first-request") String header)
    {
        System.out.print(header);
        return "Hello world in first service";
    }

서버로부터 "first-request"라는 이름의 헤더를 요청 헤더로 받겠다. ->

.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"))

프록시가 부여

요청 시 지정한 request header가 껴서 전달되고
응답에도 지정한 response header가 껴서 전달됨을 알 수 있다.

즉, 클라이언트 값을 중간에 가로채서
리퀘스트 혹은 리스폰스 값을 부여하는 역할을 함

  • 방법3) yaml에 필터 추가
mvc:
        ...
            predicates:
              - Path=/first-service/** 
            filters:
              - AddRequestHeader=first-request, first-requests-header2
              - AddResponseHeader=first-response, first-response-header2
       ...
            predicates:
              - Path=/second-service/**
            filters:
              - AddRequestHeader=second-request, second-requests-header2
              - AddResponseHeader=second-response, second-response-header2

Filters

CustomFilter

  • 라우팅 정보마다 다르게 필터 적용할 때 사용하는 커스텀 필터
    gateway:
        routes:
          - id: first-service #when the service comes in,
            uri: http://localhost:8081/ #192.168.45.104 #allocate it at this port
            predicates:
              - Path=/first-service/** #when first-service comes, allocate 8081 port
            filters:
              - CustomFilter
          - id: second-service
            uri: http://localhost:8082/ #192.168.45.104
            predicates:
              - Path=/second-service/**
            filters:
              - CustomFilter

GlobalFilter

  • 공통적인 필터 적용하기
  • yml파일에 메세지, pre,post 여부 bool값으로 등록하고 -> config 클래스 내 같은 이름의 설정 변수 만들어 yml값 그대로 끌고와 -> 구현 클래스에선 이 값을 그대로 if(true) ~~~ 적용 가능
  • 글로벌 -> 커스텀 (pre - post) -> 글로벌 끝 순서
    gateway:
      default-filters:
        - name: GlobalFilter
          args:
            baseMessage: Spring Cloud Gateway Global Filter
            preLogger: true
            postLogger: true
      routes:

적용 후 모습

적용 된 순서 참고.

LoggingFilter

  • 커스텀 필터에 글로벌 필터를 끼얹은 느낌일까
  • 설정 아래와 같이 가능 (name: <- args 작성하기 위해 추가됨)
            filters:
              - name: CustomFilter
              - name: LoggingFilter
                args:
                  baseMessage: Hi, there.
                  preLogger: true
                  postLogger: true

이런 순서로 적용될 예정

적용 후 모습

가장 마지막 수행됨.

❗ 만약 가장 최우선으로 두고 싶다면
apply함수의 OrderedGatewayFilter에 Ordered.LOWEST_PRECEDENCE을
Ordered.HiGHEST_PRECEDENCE로 변경해주자.

profile
(구) https://hansjour.tistory.com/ 이사옴. 성장하는 하루를 쌓아가는 블로그

0개의 댓글