Post
KO

Spring Cloud Gateway

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 로는 이렇게 동작합니다.

​

![](/assets/images/posts/222925794686/dd000a4c00a2.png)

​

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의 전체 설정이다.

​

Route Predicate Factories

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들을 유지보수하는데 유용할 수 있다.

​

GatewayFilter Factories

Route filter들은 들어오는 Http request 또는 나가는 Http Response를 수정할 수 있다. Route filter들은 부분적인 route로 묶여진다. Spring Cloud Gateway는 많은 내장 GatewayFilter Factories를 포함하고 있다.

​

자세한 예제는 test code를 참조

​

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}

Global Filters

​

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

​

HttpHeaderFilter들은 downstream에 보내기전에 NettyRoutingFilter를 이용해서 request들에 적용시킵니다.

​

Filter 종류

​

  1. Forwarded Header Filtter

  2. RemoveHopByHop Header filter

    The default removed headers are:

- Connection

- Keep-Alive

- Proxy-Authenticate

- Proxy-Authorization

- TE

- Trailer

- Transfer-Encoding

- Upgrade

​

  1. XForwarded Headers Filter

XForwarded 헤더 필터는 다운스트림 서비스로 보낼 다양한 X-Forwarded-* 헤더를 생성합니다. 다양한 헤더를 생성하기 위해 현재 요청의 호스트 헤더, 체계, 포트 및 경로를 사용합니다.

​

TLS and SSL

​

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

Configuration

​

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에서 사용할 수 있습니다.

​

Route Metadata Configuration

​

각 경로에 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);

Http timeouts configuration

​

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 Configuration

​

​

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로 평가되지 않을 때 유용합니다.

​

Actuator API

​

/gateway actuator endpoint는 Spring Cloud Gateway application의 활동을 모니터링 할 수 있습니다. 원격으로 접근할 수 있고, 엔드포인트는 애플리케이션 속성에서 HTTP 또는 JMX를 통해 활성화되고 노출되어야 합니다.

​

enabled

exposed over HTTP or JMX

​

application.properties

management.endpoint.gateway.enabled=true # default value management.endpoints.web.exposure.include=gateway

​

This article is licensed under CC BY 4.0 by the author.