Spring Cloud Gateway
크롬 번역으로 보는게 훨씬 좋음
https://spring.io/projects/spring-cloud-gateway
Glossary
Route
gateway의 기본 골격이다. id로 정의되고 목적지 URI, 단정문(predicate)의 묶음, 그리고 filter의 묶음이다. Route는 true조건의 경우 연결 시켜준다.
Predicate
- 이것은 java 8의 predicate이다. input type은 spring framework ServerWebExchange이다. Predicate는 Http Request나 header, parameter의 어떤 것으로 매칭시킵니다.
Filter
- GatewayFilter의 인스턴스들은 특정한 factory와 함께 생성 됩니다. 여기에는 down stream request를 보내기 전과 후로 request와 response를 갱신할 수 있습니다.
How it Works
Spring Cloud Gateway는 high-level overview 로는 이렇게 동작합니다.

Client들은 Spring cloud gateway로 요청들을 만듭니다. 만약 Gateway Hanlder Mapping은 reuqest가 매칭된 route를 결정하고, Gateway Web Handler로 전달합니다. 이 handler는 그 리퀘스트들은 특정한 요청의 filter chain 통해서 동작합니다.
점선으로 나뉘어진 필터는 request를 보내기 전/후로 logic을 같이 동작할 수 있습니다.
모든 pre filter 로직은 실행됩니다. 그리고 그 proxy request가 만들어집니다. proxy request가 만들어 진 뒤, post filter logic이 실행됩니다.
Configuring Route Predicate factories and Gateway Filter Factories
predicates들과 fitler들의 설정하는 방법은 shortcuts과 전체적으로 확장된 argument 두가지 방법이 있다.
모든 예제들은 아래 shortcut 방법을 사용한다.
code로 argument name들과 name은 첫번째로 정의되거나 각각 두개의 섹션으로 목록화된다. 그 argument들은 shortcut configuration을 위해 필요하게 된 특별한 목록이다.
Shortcut Configuration
Shortcut configuration은 filter 이름으로 알려진다. = 사진을 따르고, argument value들은 ,로 나뉘어진다.
application.yml
spring: cloud: gateway: routes: - id: after_route uri: <https://example.org> predicates: - Cookie=mycookie,mycookievalue 위 예제에서는 Cookie Route 두개의 argument들의 Predicate Factory로 정의 되어 있다. 그 cookie 이름은 mycookie와 mycookievalue의 값으로 매치된다.
Fully Expaneded Arguments
전체적으로 확장된 argument들은 기본적인 name/value 쌍의 yaml 설정으로 나타낸다.
특별한, name 키와 args 키로 된다. 그 args 키는 key value 쌍의 map으로 predicate 또는 filter로 설정된다.
application.yml
spring: cloud: gateway: routes: - id: after_route uri: <https://example.org> predicates: - name: Cookie args: name: mycookie regexp: mycookievalue 이것은 cookie predication을 보여주는 shotcut configuration의 전체 설정이다.
Spring WebFlux HanlderMapping infrastructure의 부분으로 Spring Cloud Gateway 경로가 매치된다.
Spring Cloud Gateway 는 많은 내장된 route predicate factory들을 포함하고 있다. 그런 모든 predicate들은 그 Http Request의 다른 속성들과 연결된다. 당신은 statement와 논리적인 predicate factories들로 다중 route를 조합할 수 있다. (= combine multiple route predicate factories with logical and statements)
The After Route Predicate Factory
그 After route predicate factory는 datetime 같은 1개의 parameter를 획득한다.. 이것은 predicate 특별한 datetime 이후에 발생한 요청들을 매칭한다. 예제는 after route predicate 설정을 따른다.
application.yml
spring: cloud: gateway: routes: - id: after_route uri: <https://example.org> predicates: - After=2017-01-20T17:42:47.789-07:00[America/Denver] 이 route 는 어떤 요청을 after Jan 20, 2017 17:42 Mountain Time 이후로 매치시킨다.
The Before Route Predicate Factory
before route predicate factory는 1개의 datetime parameter를 획득한다. 이 predicate는 특별한 datetime 전으로 모든 요청들을 매칭한다.
application.yml
spring: cloud: gateway: routes: - id: before_route uri: <https://example.org> predicates: - Before=2017-01-20T17:42:47.789-07:00[America/Denver] 이 route 는 어떤 request도 e Jan 20, 2017 17:42 Mountain Time 이전으로 매치시켜준다.
The Between Route Predicate Factory
Between route predicate factory는 2개의 parameter (datetime1과 datetime2 java ZonedDateTime object 같은) 취할 수 있다. 이 predicate는 모든 request들을 datetime1은 이전으로 datetime2는 이후로 매치한다. datetime2 parameter는 반드시 datetime1 이후이다. 이런 예제는 between route predicate로 설정한다.
application.yml
spring: cloud: gateway: routes: - id: between_route uri: <https://example.org> predicates: - Between=2017-01-20T17:42:47.789-07:00[America/Denver], 2017-01-21T17:42:47.789-07:00[America/Denver] 이 route는 어떤 request들을 Jan 20, 2017 17:42 Mountain Time 이후와 Jan 21, 2017 17:42 Mountain Time (Denver) 으로 매치한다. 이것은 windows들을 유지보수하는데 유용할 수 있다.
Route filter들은 들어오는 Http request 또는 나가는 Http Response를 수정할 수 있다. Route filter들은 부분적인 route로 묶여진다. Spring Cloud Gateway는 많은 내장 GatewayFilter Factories를 포함하고 있다.
The AddRequestHeader GatewayFilter Factory
AddRequestHeader, GatewayFilter factory는 name, value 파라미터를 획득합니다. AddRequestHeader, GatewayFilter 설정 예제를 확인해보자.
application.yml
spring: cloud: gateway: routes: - id: add_request_header_route uri: <https://example.org> filters: - AddRequestHeader=X-Request-red, blue X-Request-read:blue header를 downstream 모든 요청 헤더에 넣어준다.
AddRequestHeader는 경로 또는 호스트를 일치시키는 데 사용되는 URI 변수를 알고 있습니다. URI 값들은 아마도 값들로 사용되고, rumtime시에 확장된다. AddRequestHeader GatewayFilter의 예제는 아래를 참고하면 된다.
application.yml
spring: cloud: gateway: routes: - id: add_request_header_route uri: <https://example.org> predicates: - Path=/red/{segment} filters: - AddRequestHeader=X-Request-Red, Blue-{segment} AddRequestParameter GatewayFilter Factory
AddRequestParameter GatewayFilter Factory는 name과 value parameter를 획득할 수 있다. AddRequestParameter GatewayFilter 예제 설정을 참고하자.
application.yml
spring: cloud: gateway: routes: - id: add_request_parameter_route uri: <https://example.org> filters: - AddRequestParameter=red, blue downstream의 모든 매칭된 Requests들의 query string에 red=blue가 추가된다.
AddRequestParameter는 경로 또는 호스트를 일치시키는 데 사용되는 URI 변수를 알고 있습니다. URI 값들은 runtime시에 확장되는 값들로 사용됩니다. AddRequestParameter GatewayFilter는 설정 예제를 참고하자.
application.yml
spring: cloud: gateway: routes: - id: add_request_parameter_route uri: <https://example.org> predicates: - Host: {segment}.myhost.org filters: - AddRequestParameter=foo, bar-{segment} The AddResponseHeader GatewayFilter Factory
AddResponseHeader Gateway Filter Factory는 name과 value 파라미터를 획득할 수 있다. AddResponseHader GatewayFilter 설정 예제를 따른다.
application.yml
spring: cloud: gateway: routes: - id: add_response_header_route uri: <https://example.org> filters: - AddResponseHeader=X-Response-Red, Blue request 의 downstream 응답 Header에 X-Response-Red:Blue를 추가한다.
AddResponseHeader는 경로 또는 호스트를 일치시키는 데 사용되는 URI 변수를 알고 있다. URI 변수들은 runtime시에 값들로 사용된다. AddResponseHeader GatewayFilter 설정 예제를 따른다.
application.yml
spring: cloud: gateway: routes: - id: add_response_header_route uri: <https://example.org> predicates: - Host: {segment}.myhost.org filters: - AddResponseHeader=foo, bar-{segment}
GlobalFilter interface는 동일한 GatewayFilter 시그니처를 가지고 있습니다. 이는 모든 경로에 조건부로 적용되는 특수 필터 입니다.
Combined Global Filter and GatewayFilter Ordering
request가 route에 매치될 때, GlobalFilter의 모든 인스턴스들과 모든 특별한 GatewayFilter들은 Filter Chain으로 web handler에 추가 됩니다. 이런 복합된 filter chain은 org.springframework.core.Ordered interface로 정렬 됩니다.
Spring Cloud Gateway filter logic 실행시 전과 후 사이에 판별합니다. 우선 순위가 가장 높은 필터는 “사전” 단계의 첫 번째 필터이고 “포스트” 단계의 마지막 필터입니다.
filter chain 설정은 아래 설정을 따른다.
ExampleConfiguration.java
@Bean public GlobalFilter customFilter() { return new CustomGlobalFilter(); } public class CustomGlobalFilter implements GlobalFilter, Ordered { @Override public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { log.info("custom global filter"); return chain.filter(exchange); } @Override public int getOrder() { return -1; } } Forward Routing Filter
ForwardRoutingFilter는 ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR 교환하는 URI를 찾습니다. 만약 URL이 forward scheme(such as forward://localendpoint)를 가지고 있다면, Spring DispatcherHandler의 request handle을 사용합니다. request URL의 path 부분을 forward URL안의 path로 재정의 합니다. 변하지 않는 원본 URL은 ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR 속성의 목록으로 확장됩니다.
The ReactiveLoadBalancerClientFilter
ReactiveLoadBalancerClientFilter는 ServerWebExhangeUtils.GATEWAY_REQUEST_URL_ATTR로 불리워지는 속성으로 교환될 URI를 찾습니다. 만약 URL이 lb scheme를 갖고 있다면, Srping Cloud ReactorLoadBalancer의 동일한 속성의 URI로 실제 host와 port를 보내줍니다. 변하지 않는 원본 URL은 ServerWebExhangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR 속성의 목록 입니다. 필터는 ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR 속성도 살펴보고 lb와 같은지 확인합니다.
application.yml
spring: cloud: gateway: routes: - id: myRoute uri: lb://service predicates: - Path=/service/** 기본적으로 ReactorLoadBalacer의 service instance를 찾지 못하면 503이 return된다. 404로 return하고 싶을 경우 spring.cloud.gateway.loadbalancer.use404=true 설정하면 된다.
ReactiveLoadBalancerClientFilter에서 반환된 ServiceInstance의 isSecure 값은 게이트웨이에 대한 요청에 지정된 체계를 재정의합니다. 예를들면 Htts로 Gateway로 request가 들어와도 downstream request http로 만들어버려서 ServiceIntance는 not secure로 가리킨다, 반대 상황도 적용될 수 있습니다. 그러나 게이트웨이 구성의 경로에 대해 GATEWAY_SCHEME_PREFIX_ATTR이 지정된 경우 접두사가 제거되고 경로 URL의 결과 체계가 ServiceInstance 구성을 재정의합니다.
The Nettry Routing Filter
Netty routing filter는 ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR 에 위치된 https 또는 http URL일 때 동작한다. Netty의 HttpClient를 사용하고 downstream의 proxy request를 생성한다.
…
HttpHeaderFilter들은 downstream에 보내기전에 NettyRoutingFilter를 이용해서 request들에 적용시킵니다.
Filter 종류
- Connection
- Keep-Alive
- Proxy-Authenticate
- Proxy-Authorization
- TE
- Trailer
- Transfer-Encoding
- Upgrade
- XForwarded Headers Filter
XForwarded 헤더 필터는 다운스트림 서비스로 보낼 다양한 X-Forwarded-* 헤더를 생성합니다. 다양한 헤더를 생성하기 위해 현재 요청의 호스트 헤더, 체계, 포트 및 경로를 사용합니다.
Gateway는 Spring server cofiguration으로 HTTPS request를 받을 수 있다. 예제는 다음과 같다.
application.yml
server: ssl: enabled: true key-alias: scg key-store-password: your_password key-store: classpath:scg-keystore.p12 key-store-type: PKCS12 route gateway를 Http와 Https 둘다 보낼 수 있다.
불안전한 trust manager을 설정할 수도 있다.
spring: cloud: gateway: httpclient: ssl: useInsecureTrustManager: true 잘 알려진 증명서로도 설정할 수 있다.
spring: cloud: gateway: httpclient: ssl: trustedX509Certificates: - cert1.pem - cert2.pem 만약 Spring Cloud Gateway가 인증서들을 신뢰하지 못한다면, 기본 trust store가 사용되어진다. (java.net.ssl.trustStore System properties를 overridde할 수 있다.)
TLS Handshake
Gateway는 client의 backend의 경로들을 사용할 수 있다. Https로 통신할 때, Client는 TLS handshake를 초기화한다. timeout의 설정값은 이 handshake와 관련되어 있다. timeout의 설정은 다음과 같이 설정할 수 있다.
application.yml
spring: cloud: gateway: httpclient: ssl: handshake-timeout-millis: 10000 close-notify-flush-timeout-millis: 3000 close-notify-read-timeout-millis: 0
Spring Cloud Gateway RouteDefinitionLocator instance들의 묶음으로 설정된다. RouteDefinitionLocator interface로 정의된 listing된다.
public interface RouteDefinitionLocator { Flux getRouteDefinitions(); } 기본적으로 PropertiesRouteDefinitionLocator는 Spring Boot의 @ConfigurationProperties 매커니즘에 의해 load된다.
application.yml
spring: cloud: gateway: routes: - id: setstatus_route uri: <https://example.org> filters: - name: SetStatus args: status: 401 - id: setstatusshortcut_route uri: <https://example.org> filters: - SetStatus=401 일부 게이트웨이 사용의 경우 속성이 적절하지만 일부 프로덕션 사용 사례에서는 데이터베이스와 같은 외부 소스에서 구성을 로드하는 것이 좋습니다. 향후 마일스톤 버전에는 Redis, MongoDB 및 Cassandra와 같은 Spring 데이터 저장소를 기반으로 하는 RouteDefinitionLocator 구현이 있습니다.
RouteDefinition Metric
Spring-boot-starter-actuator를 project dependency에 추가하면 RouteDefinition mertics을 사용할 수 있다. 기본적으로 spring.cloud.gateway.metrics.enabled는 true로 설정되어 있다.
값이 RouteDefinitions의 수 인 spring.cloud.gateway.routes.count라는 게이지 메트릭이 추가됩니다.
이 메트릭은 /actuator/metrics/spring.cloud.gateway.routes.count에서 사용할 수 있습니다.
각 경로에 metadata를 추가적인 설정을 할 수 있습니다.
application.yml
spring: cloud: gateway: routes: - id: route_with_metadata uri: <https://example.org> metadata: optionName: "OptionValue" compositeObject: name: "value" iAmNumber: 1 교환으로 부터 모든 metadata properties를 획득할 수 있다.
Route route = exchange.getAttribute(GATEWAY_ROUTE_ATTR); // get all metadata properties route.getMetadata(); // get a single metadata property route.getMetadata(someKey);
global http timeout 설정
connect-timeout 은 반드시 milliseconds로 설정해야 한다.
response-timeout 은 반드시 java.time.duration 으로 설정해야 한다.
설정 예시
spring: cloud: gateway: httpclient: connect-timeout: 1000 response-timeout: 5s Per-route timeouts
(경로별 timeout 설정)
connect-timeout은 반드시 milliseconds로 작성되야한다.
response-timeout은 반드시 milliseconds로 작성되야한다.
- id: per_route_timeouts uri: <https://example.org> predicates: - name: Path args: pattern: /delay/{timeout} metadata: response-timeout: 200 connect-timeout: 200
per-route timeout Java DSL 설정
import static org.springframework.cloud.gateway.support.RouteMetadataUtils.CONNECT_TIMEOUT_ATTR; import static org.springframework.cloud.gateway.support.RouteMetadataUtils.RESPONSE_TIMEOUT_ATTR; @Bean public RouteLocator customRouteLocator(RouteLocatorBuilder routeBuilder){ return routeBuilder.routes() .route("test1", r -> { return r.host("*.somehost.org").and().path("/somepath") .filters(f -> f.addRequestHeader("header1", "header-value-1")) .uri("http://someuri") .metadata(RESPONSE_TIMEOUT_ATTR, 200) .metadata(CONNECT_TIMEOUT_ATTR, 200); }) .build(); } 각 경로별 response-timeout의 값을 음수로하면 설정되지 않는다.
- id: per_route_timeouts uri: <https://example.org> predicates: - name: Path args: pattern: /delay/{timeout} metadata: response-timeout: -1 Java Routes API
// static imports from GatewayFilters and RoutePredicates @Bean public RouteLocator customRouteLocator(RouteLocatorBuilder builder, ThrottleGatewayFilterFactory throttle) { return builder.routes() .route(r -> r.host("**.abc.org").and().path("/image/png") .filters(f -> f.addResponseHeader("X-TestHeader", "foobar")) .uri("http://httpbin.org:80") ) .route(r -> r.path("/image/webp") .filters(f -> f.addResponseHeader("X-AnotherHeader", "baz")) .uri("http://httpbin.org:80") .metadata("key", "value") ) .route(r -> r.order(-1) .host("**.throttle.org").and().path("/get") .filters(f -> f.filter(throttle.apply(1, 1, 10, TimeUnit.SECONDS))) .uri("http://httpbin.org:80") .metadata("key", "value") ) .build(); } 이 스타일은 커스텀 predicate assertions도 허용한다. RouteDefinitionLocator bean의 predicates 설정은 and를 사용하여 조합한다. Predicate class의 and(), or(), negate() operator들을 사용할 수 있다.
DiscoveryClient Route definition Locator
Gateway 설정 중 경로를 DiscoveryClient 서비스 registry를 이용하여 생성할 수 있다.
설정을 켜는 방법은 spring.cloud.gateway.discovery.locator.enabled=true 로 가능하며, DiscoveryClient 구현은 Netflix Eureka, Consul, or Zookeeper를 이용할 수 있다.)
** DiscoveryClient 경로를 위한 Predicate와 filter의 설정**
기본적으로 gateway 는 1개의 predicate와 filter로 DiscoveryClient의 경로가 정의됩니다.
기본 predicate는 /serviceId/** 과 같은 pattern으로 path predicate가 정의 되고, serviceId는 DiscoveryClient의 service ID 이다.
default filter는 정규식으로 path가 재작성되고, /${remaining} 으로 변경된다. 이렇게 하면 요청이 다운스트림으로 전송되기 전에 경로에서 서비스 ID가 제거됩니다.
만약 DiscoveryClient 경로의 predicates 또는 filter를 변경하길 원하면, spring.cloud.gateway.discovery.locator.predicates[x] 와 spring.cloud.gateway.discovery.locator.filters[y] 을 설정하면 된다.
그렇게 할 때 해당 기능을 유지하려면 앞서 표시된 기본 술어 및 필터를 포함해야 합니다. 다음 예는 이것이 어떻게 생겼는지 보여줍니다.
application.properteis
spring.cloud.gateway.discovery.locator.predicates[0].name: Path spring.cloud.gateway.discovery.locator.predicates[0].args[pattern]: "'/'+serviceId+'/**'" spring.cloud.gateway.discovery.locator.predicates[1].name: Host spring.cloud.gateway.discovery.locator.predicates[1].args[pattern]: "'**.foo.com'" spring.cloud.gateway.discovery.locator.filters[0].name: CircuitBreaker spring.cloud.gateway.discovery.locator.filters[0].args[name]: serviceId spring.cloud.gateway.discovery.locator.filters[1].name: RewritePath spring.cloud.gateway.discovery.locator.filters[1].args[regexp]: "'/' + serviceId + '/?(?.*)'" spring.cloud.gateway.discovery.locator.filters[1].args[replacement]: "'/${remaining}'" Reactor Netty Access Logs
Reactor Netty access log를 활성화 하려면 -Dreactor.netty.http.server.accessLogEnabled=true 으로 설정한다.
logback.xml
access_log.log %msg%n
CORS 설정을 할 수 있다. global CORS 설정 Spring framework의 CorsConfiguration의 URL 패턴이다.
예제는 다음과 같다.
spring: cloud: gateway: globalcors: cors-configurations: '[/**]': allowedOrigins: "https://docs.spring.io" allowedMethods: - GET 예제에서 CORS reuqest들은 “docs.spring.io”의 모든 Get request path를 허용한다.
일부 게이트웨이 경로 술어에서 처리하지 않는 요청에 동일한 CORS 구성을 제공하려면 spring.cloud.gateway.globalcors.add-to-simple-url-handler-mapping 속성을 true로 설정하십시오. 이는 CORS 실행 전 요청을 지원하려고 하고 HTTP 메서드가 옵션이기 때문에 경로 조건자가 true로 평가되지 않을 때 유용합니다.
/gateway actuator endpoint는 Spring Cloud Gateway application의 활동을 모니터링 할 수 있습니다. 원격으로 접근할 수 있고, 엔드포인트는 애플리케이션 속성에서 HTTP 또는 JMX를 통해 활성화되고 노출되어야 합니다.
application.properties
management.endpoint.gateway.enabled=true # default value management.endpoints.web.exposure.include=gateway