Spring Cloud Gateway
Spring Cloud Gateway는 마이크로 서비스 아키텍처에서의 진입점으로 사용되는 서비스이다. 이 서비스는 다양한 기능을 제공하여 마이크로 서비스 간의 통신과 관리를 용이하게 만든다.
- Spring Cloud Gateway는 비동기 방식으로 동작하며, Netty를 사용하여 효율적인 네트워크 통신을 지원한다.
- Predicates는 요청을 어떤 서비스로 라우팅할지 결정하는 역할을, Filter는 요청 및 응답에 대한 추가적인 로직을 수행하며, 이 두 가지를 조합하여 유연한 라우팅 및 처리를 가능케 한다.
- 사용자의 인증 및 권한 부여를 관리하여 보안을 강화한다
- 마이크로 서비스의 동적인 변화에 대응하기 위해 서비스 검색을 통합하여 서비스 간의 통신을 간편하게 처리한다.
- 응답 캐싱을 통해 빠른 응답 속도를 유지하고 중복된 요청을 효율적으로 처리한다.
- 정책 관리, 회로 차단, 및 QoS 다시 시도를 통해 안정적이고 예측 가능한 서비스 동작을 지원한다.
- 요청 속도를 제한하여 서비스에 대한 부하를 관리하고 과부하를 방지한다.
- 서비스 간의 부하를 균등하게 분산하여 확장성을 향상시킨다.
- 로깅, 추적, 상관관계 관리를 통해 서비스 동작을 모니터링하고 문제를 신속하게 해결할 수 있다.
- 헤더와 쿼리 문자열을 변환하고 처리하여 서비스 간의 통신을 유연하게 조절할 수 있다.
- 특정 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)
}
}
728x90
'JVM > SpringCloud' 카테고리의 다른 글
Spring Cloud Bus (0) | 2023.12.28 |
---|---|
Spring Cloud Config (0) | 2023.12.27 |
[SpringCloud] Swagger(Springdoc) 통합 설정 (0) | 2023.12.27 |
Spring Gateway, Eureka 연동 (0) | 2023.09.03 |
Spring Cloud Netflix Eureka (0) | 2023.08.23 |