오늘의하루

[Spring Cloud 2일차] API Gateway 필터 순서 및 Eureka Load Balancing 본문

Spring/Cloud

[Spring Cloud 2일차] API Gateway 필터 순서 및 Eureka Load Balancing

오늘의하루_master 2024. 9. 11. 14:21

Spring Cloud Gateway에서 API Gateway 필터 구성하기

사용자 정의 필터를 생성하려면 AbstractGatewayFilterFactory를 상속 받은 후 apply 메서드를 구현한다.

GatewayFilter를 반환해야 하며 GatewayFilter를 구현한 OrderedGatewayFilter로 생성하면 실행 순서를 지정할 수 있다.

OrderedGatewayFilter는 Ordered도 구현하고 있는데 Ordered 객체 안에는 HIGHEST_PRECEDENCE (Integer.MIN_VALUE)와 LOWEST_PRECEDENCE(Integer.MAX_VALUE)가 있어서 가장 먼저 실행되야 하는것과 가장 마지막에 실행되어야 한는 필터의 순서를 쉽게 지정해줄 수 있다.

추가 ) Filter의 우선 순위는 낮을수록 먼저 실행되나.

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

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

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

      log.info("Logging Filter baseMessage : {}", config.getBaseMessage());

      if(config.isPreLogger()) {
        log.info("Logging PRE Filter Start : request id = {}", request.getId());
      }

      return chain.filter(exchange).then(Mono.fromRunnable(() -> {
        if(config.isPostLogger()){
          log.info("Logging Filter End : response code = {}", response.getStatusCode());
        }
      }));
    }, OrderedGatewayFilter.LOWEST_PRECEDENCE); // 가장 낮은 순서를 갖는다. (Integer.MAX_VALUE)
  }

  @Data
  public static class Config {
   private String baseMessage;
   private boolean preLogger;
   private boolean postLogger;
 }
}

하나의 Route에 여러개의 필터 적용

application.yml에서 여러 Filter를 Route에 적용할 수 있는데 Filter에 우선 순위를 별도로 지정하지 않은 경우 나열된 순서대로 적용된다.

spring:
  application:
    name: apigateway-service
  cloud:
    gateway:
      default-filters:
        - name: globalFilter
          args:
            baseMessage: Global Filter
            preLogger: true
            postLogger: true
    routes:
      - id: first-service
        uri: http://localhost:8081
        predicates:
          - Path=/first-service/**
        filters:
          - CustomFilter
          - NoArgsFilter
      - id: second-service
        uri: http://localhost:8082
        predicates:
          - Path=/second-service/**
        filters:
          - name: CustomFilter
          - name: LoggingFilter
            args:
              baseMessage: Logging Filter
              preLogger: true
              postLogger: true

만약 Filter가 인자( AbstractGatewayFilterFactory 제네릭 타입 파라미터 객체 )를 초기화 하고 싶다면 해당 Route의 모든 Filter앞에 - name:을 붙여줘야 하며 그렇지 않은 상황에서는 name:은 생략이 가능하다.

Eureka와 통합하여 서비스 사용

동작 순서

Client -> API Gateway(실제 서비스 URL X) -> Eureka(해당 서비스 URL search) -> API Gateway(실제 서비스 URL O) -> MicroService -> API Gateway -> Clinet

server:
  port: 8000

eureka:
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      defaultZone: http://localhost:8761/eureka

spring:
  application:
    name: apigateway-service
  cloud:
    gateway:
      default-filters:
        - name: GlobalFilter
          args:
            baseMessage: Spring Cloud GateWay Global Filter
            preLogger: true
            postLogger: true
      routes:
        - id: first-service
          uri: lb://MY-FIRST-SERVICE
          predicates:
            - Path=/first-service/**
          filters:
            - CustomFilter
        - id: second-service
          uri: lb://MY-SECOND-SERVICE
          predicates:
            - Path=/second-service/**
          filters:
            - name: CustomFilter
            - name: LoggingFilter
              args:
                baseMessage: Hi, threr.
                preLogger: true
                postLogger: true
  • 각 Route의 uri는 lb://로 시작하며 뒤에는 Eureka에 등록된 서비스 이름을 작성
    • 등록된 서비스 이름은 실제 서비스의 application.name을 대문자로 치환한 것이다.
  • Eureka는 자동으로 서비스 인스턴스 간에 라운드 로빈 방식으로 로드 밸런싱 처리
Comments