Sprign Cloud - Filter 만들기

연어는결국강으로·2023년 2월 21일
0

MSA

목록 보기
2/7

Api Gateway에 CustomFilter를 넣어보는 강의이다.

💻CustomFilter

1. CustomFilter 뼈대 만들기

@Component
@Slf4j
public class CustomFilter extends AbstractGatewayFilterFactory<CustomFilter.Config> {

    public CustomFilter() {
        super(Config.class);
    }

    public static class Config {
        // Put the configuration properties
    }

    @Override
    public GatewayFilter apply(Config config) {
        // Custom PreFilter
		return null;
        });
    }
}
  • CustomFilter클래스를 만들고 AbstractGatewayFilterFactory를 상속 받는다.
  • CustomFilter에 내부 정적 클래스 Config를 만든다. 이 클래스에는 설정 값들을 넣는다. 현재는 특별한게 없어서 저렇게 주석처리 해놓은 상태이다.
  • 생성자를 만든다.
  • apply 메서드를 오버라이딩한다.
  • 위의 코드는 여기까지 한 내용이다.

2. apply 메서드

    @Override
    public GatewayFilter apply(Config config) {
        // Custom PreFilter
        return ((exchange, chain) -> {
            ServerHttpRequest request = exchange.getRequest();
            ServerHttpResponse response = exchange.getResponse();

            log.info("Custom PRE filter : request id -> {}", request.getId());

            // Custom Post Filter
            return chain.filter(exchange).then(Mono.fromRunnable(() -> {
                log.info("Custom POST filter : response code -> {}", response.getStatusCode());
            }));

        });
    }
  • apigateway는 WebFlux에서 배우던 netty기반 서버라고 한다. 따라서 reactive 패키지에 있는 ServerHttpRequest를 사용해야 한다.
  • return 에 두가지 인자가 있는 것은 GatewayFilter 의 생성자 중에 exchange와 chain을 받는 녀석이 있는 모양이다.
  • 요청을 받았을때 로그를 한번 찍고, 응답을 받을 때 로그를 찍는 것으로 매서드는 끝이다.

3. 부가적인 녀석들

server:
  port: 8000


spring:
  application:
    name: api-gateway-service
  cloud:
    gateway:
      routes:
        - id: first-service
          uri: http://localhost:8081/
          predicates:
            - Path=/first-service/**
          filters:
#              - AddRequestHeader=first-request, first-requests-header2
#              - AddResponseHeader=first-response, first-response-header2
              - CustomFilter
        - id: second-service
          uri: http://localhost:8082/
          predicates:
            - Path=/second-service/**
          filters:
#            - AddRequestHeader=second-request, second-requests-header2
#            - AddResponseHeader=second-response, second-response-header2
            - CustomFilter
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka
    register-with-eureka: false
    fetch-registry: false
  • yaml 파일에서는 기존의 필터를 주석처리하고 CustomFilter를 등록했다.
  • 또한 FirstService와 SecondService에 check() 매서드를 등록했다.
  • check로 들어가보면 아래와 같은 로그가 api gateway에 남는다.

💻Global Filter

  • Global Filter 즉 전역에서 작동하는 필터는 Custom Filter와 비슷하다.
  • 이번엔 좀 새로운게 추가되었는데, 이전에 사용했던 정적 클래스에 값을 추가해서 사용했다.
    @Data
    public static class Config {
        private String baseMessage;
        private boolean preLogger;
        private boolean postLogger;
    }
  • 요즘 한참 Entity에 setter를 넣어서 사용해 온 것 때문에 무한자괴감을 느끼고 있어서 @Data가 아닌 @Getter만 넣고 사용하려고 했는데, 다음에 나올 yaml파일에서 에러가 났다. 이걸 한참 찾았다.
    gateway:
      default-filters:
           - name: GlobalFilter
             args:
                baseMessage: Spring Cloud Gateway Global Filter
                preLogger: true
                postLogger: true
  • 이렇게 야물파일에 값을 추가하는데, 이 녀석들이 setter로 작동하는 녀석들이라 setter가 없는 내 내부정적클래스에서는 이 녀석들을 받아들일 수가 없었던 것이었다.

  • 아무튼 이렇게 하고 작동시키면 아래처럼 로그가 잘 나온다.


💻Logging Filter

    @Override
    public GatewayFilter apply(Config config) {
        // Custom PreFilter
        GatewayFilter filter = new OrderedGatewayFilter((exchange, chain) -> {
            ServerHttpRequest request = exchange.getRequest();
            ServerHttpResponse response = exchange.getResponse();

            log.info("Logging PRE filter : request id -> {}", request.getId());

            // Custom Post Filter
            return chain.filter(exchange).then(Mono.fromRunnable(() -> {
                log.info("Logging POST filter : response code -> {}", response.getStatusCode());
            }));
            
        // 이 녀석!!!
        }, Ordered.HIGHEST_PRECEDENCE);

        return filter;
    }
  • logging filter는 앞선 필터와 별 다르지 않다.
  • 그러나 이번에는 GatewayFilter 인터페이스의 구현체인 OrderedGatewayFilter로 구현하게 되었는데 이것은 Ordered.~~라는 실행순서에 대한 설정값이 있다.
  • 위의 설정은 로깅 필터를 가장 먼저 실행하게 된다.

  • 실제 로그를 보면 위와 같다. 아래 그림과 같은 순서를 기대했는데 그렇지 못했다.

  • 아까 Ordered를 Ordered.LOWEST_PRECEDENCE 이렇게 바꾸면

  • 기대한 대로 로그가 뜨기는 한다.

  • 그런데 이게 우리가 진정 의도한 것인가 하면 그건 아닌거같다. 그저 맨 나중에 실행되게 했을 뿐이다. yml파일에 로깅필터 아래에 다른 필터를 추가한다 해도 로깅필터가 맨 나중에 실행될 것이다.

  • 그럼 어떻게 해야되는 것인가... 그걸 알려주고 강의가 끝날줄 알았는데 그냥 끝나버렸다.

  • 나도 여기서 마무리해야 할거 같다!!

0개의 댓글