JVM/SpringCloud

Spring Cloud Gateway

kyoulho 2023. 8. 23. 16:03

Spring Cloud Gateway


Spring Cloud Gateway는 마이크로 서비스 아키텍처에서의 진입점으로 사용되는 서비스이다. 이 서비스는 다양한 기능을 제공하여 마이크로 서비스 간의 통신과 관리를 용이하게 만든다.

  1. Spring Cloud Gateway는 비동기 방식으로 동작하며, Netty를 사용하여 효율적인 네트워크 통신을 지원한다.
  2. Predicates는 요청을 어떤 서비스로 라우팅할지 결정하는 역할을, Filter는 요청 및 응답에 대한 추가적인 로직을 수행하며, 이 두 가지를 조합하여 유연한 라우팅 및 처리를 가능케 한다.
  3. 사용자의 인증 및 권한 부여를 관리하여 보안을 강화한다
  4. 마이크로 서비스의 동적인 변화에 대응하기 위해 서비스 검색을 통합하여 서비스 간의 통신을 간편하게 처리한다.
  5. 응답 캐싱을 통해 빠른 응답 속도를 유지하고 중복된 요청을 효율적으로 처리한다.
  6. 정책 관리, 회로 차단, 및 QoS 다시 시도를 통해 안정적이고 예측 가능한 서비스 동작을 지원한다.
  7. 요청 속도를 제한하여 서비스에 대한 부하를 관리하고 과부하를 방지한다.
  8. 서비스 간의 부하를 균등하게 분산하여 확장성을 향상시킨다.
  9. 로깅, 추적, 상관관계 관리를 통해 서비스 동작을 모니터링하고 문제를 신속하게 해결할 수 있다.
  10. 헤더와 쿼리 문자열을 변환하고 처리하여 서비스 간의 통신을 유연하게 조절할 수 있다.
  11. 특정 IP 주소나 범위를 허용 목록에 추가하여 보안을 강화할 수 있다.

 

기본적인 라우팅 설정


server:
  port: 8000

eureka:
  client:
    register-with-eureka: false
    fetch-registry: false
    service-url:
      defaultZone: https://localhost:8761/eureka

spring:
  application:
    name: apigateway-service
  cloud:
    gateway:
      routes:
# http://localhost:8080/first-service/** 으로 요청이 오면
# http://localhost:8081/first-service/** 으로 라우팅 한다
        - id: first-service
          uri: http://localhost:8081
          predicates:
            - Path=/first-service/**
        - id: second-service
          uri: http://localhost:8082
          predicates:
            - Path=/second-service/**

 

필터 적용


코드 방식

@Configuration
class FilterConfig {
    @Bean
    fun gatewayRoutes(builder: RouteLocatorBuilder): RouteLocator {
        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()
    }
}

properties 방식

spring:
  application:
    name: gateway-service
  cloud:
    gateway:
      routes:
        - id: first-service
          uri: http://localhost:8081
          predicates:
            - Path=/first-service/**
          filters:
            - AddRequestHeader=first-request, first-request-header
            - AddResponseHeader=first-response, first-response-header
        - id: second-service
          uri: http://localhost:8082
          predicates:
            - Path=/second-service/**
          filters:
            - AddRequestHeader=second-request, second-request-header
            - AddResponseHeader=second-response, second-response-header

 

 

이미 구현된 필터들


org.springframework.cloud.gateway.filter.factory 패키지에는 이미 구현되어 있는 필터들이 있다. 위에 AddRequestHeader는 AddRequestHeaderGatewayFilterFactory 클래스를 적용하는 방법이다. 

 이외에도 요청 헤더를 지우거나 Path를 지우는 필터들도 존재한다.

spring:
  cloud:
    gateway:
      routes:
        - id: user-service-login
          predicates:
            - Path=/user-service/login
            - Method=POST
          uri: lb://USER-SERVICE
          filters:
            - RemoveRequestHeader=Cookie
            - RewritePath=/user-service/(?<segment>.*), /$\{segment}

        - id: user-service-users
          predicates:
            - Path=/user-service/users
            - Method=POST
          uri: lb://USER-SERVICE
          filters:
            - RemoveRequestHeader=Cookie
            - RewritePath=/user-service/(?<segment>.*), /$\{segment}

        - id: user-service-all
          predicates:
            - Path=/user-service/**
            - Method=GET
          uri: lb://USER-SERVICE
          filters:
            - RemoveRequestHeader=Cookie
    	    - RewritePath=/user-service/(?<segment>.*), /$\{segment}

 

 

 

커스텀 필터


필터 구현

@Component
class CustomFilter : AbstractGatewayFilterFactory<CustomFilter.Config>() {
    class Config // 설정 정보
   
    override fun apply(config: Config): GatewayFilter {
        // 커스텀 Pre filter
        return GatewayFilter { exchange: ServerWebExchange, chain: GatewayFilterChain ->
            val request = exchange.request
            val response = exchange.response
            print(request)
            
            // 그 다음 필터로
            chain.filter(exchange)
           	// 되돌아오면 해야할 로직
            	.then(Mono.fromRunnable { print(response) })
        }
    }
}

필터 등록

spring:
  application:
    name: apigateway-service
  cloud:
    gateway:
      routes:
        - id: first-service
          uri: http://localhost:8081
          predicates:
            - Path=/first-service/**
          filters:
            - CustomFilter

 

Global Filter


전역 필터는 모든 라우팅에 적용되는 필터이다. 가장 먼저 시작되고 가장 마지막에 종료된다.

필터 구현

@Component
class GlobalFilter : AbstractGatewayFilterFactory<GlobalFilter.Config>(Config::class.java) {
    data class Config(
        val baseMessage: String,
        val preLogger: Boolean,
        val postLogger: Boolean,
    )

    override fun apply(config: Config): GatewayFilter {
        return GatewayFilter { exchange: ServerWebExchange, chain: GatewayFilterChain ->
            val request = exchange.request
            val response = exchange.response
            print(config.baseMessage)
            if (config.preLogger) print(request)
            chain.filter(exchange)
            	.then(Mono.fromRunnable { if(config.postLogger) print(response) })
        }
    }

필터 등록

spring:
  application:
    name: apigateway-service
  cloud:
    gateway:
      default-filters: 
        - name: Global Filter
          args:
            baseMessage: Spring Cloud Gateway Global Filter
            preLogger: true
            postLogger: true

 

필터의 우선 순위 적용하기


OrderedGateFilter를 구현하여 필터의 우선순위를 코드에서 지정할 수 있다.

@Component
class LoggingFilter : AbstractGatewayFilterFactory<LoggingFilter.Config>(Config::class.java) {
    class Config { // 설정 정보
        val message: String = "config message"
    }

    override fun apply(config: Config): GatewayFilter {
        return OrderedGatewayFilter({ exchange, chain ->
            val request = exchange.request
            val response = exchange.response
            println(config.message)
            print(request)
            chain.filter(exchange).then(Mono.fromRunnable { print(response) })
            // 필터의 우선 순위 적용, 가장 높은 순서로 적용시 글로벌 필터 보다 먼저 작동한다.
        }, Ordered.HIGHEST_PRECEDENCE)
    }
}

 

 

 

'JVM > SpringCloud' 카테고리의 다른 글

Spring Cloud Bus  (0) 2023.12.28
Spring Cloud Config  (0) 2023.12.27
Spring Swagger(Springdoc) 통합 설정  (0) 2023.12.27
Spring Gateway, Eureka 연동  (0) 2023.09.03
Spring Cloud Netflix Eureka  (0) 2023.08.23