本文共 32647 字,大约阅读时间需要 108 分钟。
Spring Cloud Gateway旨在提供一种简单而有效的方式来对API进行路由,并为他们提供切面
,例如:安全性,监控/指标 和弹性等。
依赖Spring Boot和Spring Webflux提供的Netty runtime
。它不能在传统的Servlet容器中工作 聚合断言结果为真,则匹配
到该路由。org.springframework.cloud spring-cloud-starter-gateway
如果不希望启用网关,请进行设置spring.cloud.gateway.enabled=false
。
Spring Cloud Gateway将路由作为Spring WebFlux HandlerMapping基础结构的一部分进行匹配。Spring Cloud Gateway包含许多内置的路由断言Factories。这些断言都匹配HTTP请求的不同属性。多个路由断言Factories可以通过 and 组合使用。
After 路由断言 Factory
After Route Predicate Factory采用一个参数——日期时间。在该日期时间之后发生的请求都将被匹配。application.yml
spring: cloud: gateway: routes: - id: after_route uri: http://example.org predicates: - After=2017-01-20T17:42:47.789-07:00[America/Denver]
Before Route Predicate Factory采用一个参数——日期时间。在该日期时间之前发生的请求都将被匹配。
application.yml.
spring: cloud: gateway: routes: - id: before_route uri: http://example.org predicates: - Before=2017-01-20T17:42:47.789-07:00[America/Denver]
Between 路由断言 Factory有两个参数:datetime1和datetime2。在datetime1和datetime2之间的请求将被匹配。datetime2参数的实际时间必须在datetime1之后。
spring: cloud: gateway: routes: - id: between_route uri: http://example.org predicates: - Between=2017-01-20T17:42:47.789-07:00[America/Denver], 2017-01-21T17:42:47.789-07:00[America/Denver]
Cookie 路由断言 Factory有两个参数,cookie名称和正则表达式。请求包含次cookie名称且正则表达式为真的将会被匹配。
spring: cloud: gateway: routes: - id: cookie_route uri: http://example.org predicates: - Cookie=chocolate, ch.p
Host 路由断言 Factory包括一个参数:host name列表。使用Ant路径匹配规则,.作为分隔符。
spring: cloud: gateway: routes: - id: host_route uri: http://example.org predicates: #http://example.org的接口只允许**.somehost.org,**.anotherhost.org域名进行访问 - Host=**.somehost.org,**.anotherhost.org
Method 路由断言 Factory只包含一个参数: 需要匹配的HTTP请求方式
spring: cloud: gateway: routes: - id: method_route uri: http://example.org predicates: - Method=GET
Path 路由断言 Factory 有2个参数: 一个Spring PathMatcher表达式列表和可选matchOptionalTrailingSeparator标识 .
spring: cloud: gateway: routes: - id: host_route uri: http://example.org predicates: - Path=/foo/{ segment},/bar/{ segment}
例如: /foo/1
or /foo/bar
or /bar/baz
的请求都将被匹配
可以使用以下方法来更方便地访问这些变量。
MapuriVariables = ServerWebExchangeUtils.getPathPredicateVariables(exchange);String segment = uriVariables.get("segment");
Query 路由断言 Factory 有2个参数: 必选项 param 和可选项 regexp
spring: cloud: gateway: routes: - id: query_route uri: http://example.org predicates: - Query=baz
则包含了请求参数 baz
的都将被匹配。
spring: cloud: gateway: routes: - id: query_route uri: http://example.org predicates: - Query=foo, ba.
如果请求参数里包含foo
参数,并且值匹配为ba.
表达式,则将会被路由。
RemoteAddr 路由断言 Factory的参数为 一个CIDR符号(IPv4或IPv6)字符串的列表,最小值为1,例如192.168.0.1/16(其中192.168.0.1是IP地址并且16是子网掩码)。
spring: cloud: gateway: routes: - id: remoteaddr_route uri: http://example.org predicates: - RemoteAddr=192.168.1.1/24
如果请求的remote address 为 =192.168.1.1/24 中的地址则将被路由。
默认情况下,RemoteAddr 路由断言 Factory使用传入请求中的remote address。如果Spring Cloud Gateway位于代理层后面,则可能与实际客户端IP地址不匹配。 可以通过设置自定义RemoteAddressResolver
来自定义解析远程地址的方式。Spring Cloud Gateway网关附带一个非默认远程地址解析程序,它基于X-Forwarded-For header, XForwardedRemoteAddressResolver.
XForwardedRemoteAddressResolver 有两个静态构造函数方法,采用不同的安全方法: GatewayConfig.java:
RemoteAddressResolver resolver = XForwardedRemoteAddressResolver .maxTrustedIndex(1);....route("direct-route", r -> r.remoteAddr("10.1.1.1", "10.10.1.1/24") .uri("https://downstream1").route("proxied-route", r -> r.remoteAddr(resolver, "10.10.1.1", "10.10.1.1/24") .uri("https://downstream2"))
过滤器允许以某种方式修改传入的HTTP请求或返回的HTTP响应。过滤器的作用域是某些特定路由。Spring Cloud Gateway包括许多内置的 Filter工厂。
采用一对名称和值作为参数
spring: cloud: gateway: routes: - id: add_request_header_route uri: http://example.org filters: - AddRequestHeader=X-Request-Foo, Bar
对于所有匹配的请求,这将向下游请求的头中添加 x-request-foo:bar
头.
采用一对名称和值作为参数
spring: cloud: gateway: routes: - id: add_request_parameter_route uri: http://example.org filters: - AddRequestParameter=foo, bar
对于所有匹配的请求,这将向下游请求添加foo=bar
查询字符串
采用一对名称和值作为参数
spring: cloud: gateway: routes: - id: add_request_header_route uri: http://example.org filters: - AddResponseHeader=X-Response-Foo, Bar
对于所有匹配的请求,这会将x-response-foo:bar
头添加到下游响应的header中
Hystrix 是Netflix开源的断路器组件
。Hystrix GatewayFilter允许你向网关路由引入断路器
,保护你的服务不受级联故障的影响,并允许你在下游故障时提供fallback响应。
要在项目中启用Hystrix网关过滤器,需要添加对 spring-cloud-starter-netflix-hystrix
的依赖 Spring Cloud Netflix
.
Hystrix GatewayFilter Factory 需要一个name参数,即HystrixCommand的名称。
spring: cloud: gateway: routes: - id: hystrix_route uri: http://example.org filters: - Hystrix=myCommandName
这将剩余的过滤器包装在命令名为“myCommandName”的HystrixCommand中。
hystrix过滤器还可以接受可选的fallbackUri 参数。目前,仅支持forward: 预设的URI,如果调用fallback,则请求将转发到与URI匹配的控制器。
spring: cloud: gateway: routes: - id: hystrix_route uri: lb://backing-service:8088 predicates: - Path=/consumingserviceendpoint filters: - name: Hystrix args: name: fallbackcmd fallbackUri: forward:/incaseoffailureusethis - RewritePath=/consumingserviceendpoint, /backingserviceendpoint
当调用hystrix fallback时,这将转发到/incaseoffailureusethis
的 uri。
lb前缀
,使用Spring Cloud Netflix Ribbon 客户端负载均衡。 主要场景是使用fallbackUri 到网关应用程序中的内部控制器或处理程序。但是,也可以将请求重新路由到外部应用程序中的控制器或处理程序,如:
spring: cloud: gateway: routes: - id: ingredients uri: lb://ingredients predicates: - Path=//ingredients/** filters: - name: Hystrix args: name: fetchIngredients fallbackUri: forward:/fallback - id: ingredients-fallback uri: http://localhost:9994 predicates: - Path=/fallback
在本例中,gateway应用程序中没有 fallback 实现,但是另一个应用程序中有一个接口实现,注册为“http://localhost:9994”。
在将请求转发到fallback的情况下,Hystrix Gateway过滤还支持直接抛出Throwable 。它被作为ServerWebExchangeUtils.HYSTRIX_EXECUTION_EXCEPTION_ATTR属性添加到ServerWebExchange中,可以在处理网关应用程序中的fallback时使用。
对于外部控制器/处理程序方案,可以添加带有异常详细信息的header。可以在 FallbackHeaders GatewayFilter Factory section.中找到有关它的更多信息。
hystrix配置参数(如 timeouts)可以使用全局默认值配置,也可以使用Hystrix wiki中所述属性进行配置。
要为上面的示例路由设置5秒超时,将使用以下配置:
hystrix.command.fallbackcmd.execution.isolation.thread.timeoutInMilliseconds: 5000
FallbackHeaders允许在转发到外部应用程序中的FallbackUri的请求的header中添加Hystrix异常详细信息,如下所示:
spring: cloud: gateway: routes: - id: ingredients uri: lb://ingredients predicates: - Path=//ingredients/** filters: - name: Hystrix args: name: fetchIngredients fallbackUri: forward:/fallback - id: ingredients-fallback uri: http://localhost:9994 predicates: - Path=/fallback filters: - name: FallbackHeaders args: executionExceptionTypeHeaderName: Test-Header
在本例中,在运行HystrixCommand发生执行异常后,请求将被转发到 localhost:9994应用程序中的 fallback终端或程序。异常类型、消息(如果可用)cause exception类型和消息的头,将由FallbackHeaders filter添加到该请求中。
通过设置下面列出的参数值及其默认值,可以在配置中覆盖headers的名称:
executionExceptionTypeHeaderName ("Execution-Exception-Type") executionExceptionMessageHeaderName ("Execution-Exception-Message") rootCauseExceptionTypeHeaderName ("Root-Cause-Exception-Type") rootCauseExceptionMessageHeaderName ("Root-Cause-Exception-Message")
PrefixPath GatewayFilter 只有一个 prefix 参数.
spring: cloud: gateway: routes: - id: prefixpath_route uri: http://example.org filters: - PrefixPath=/mypath
这将给所有匹配请求的路径加前缀/mypath
。因此,向/hello
发送的请求将发送到/mypath/hello
。
该filter没有参数。设置了该Filter后,GatewayFilter将不使用由HTTP客户端确定的host header ,而是发送原始host header
spring: cloud: gateway: routes: - id: preserve_host_route uri: http://example.org filters: - PreserveHostHeader
RequestRateLimiter使用RateLimiter实现是否允许继续执行当前请求。如果不允许继续执行,则返回HTTP 429 - Too Many Requests (默认情况下)。
这个过滤器可以配置一个可选的keyResolver 参数和rate limiter参数(见下文)。
keyResolver 是 KeyResolver 接口的实现类.在配置中,按名称使用SpEL引用bean。#{@myKeyResolver} 是引用名为’myKeyResolver’的bean的SpEL表达式。
KeyResolver.java
public interface KeyResolver { Monoresolve(ServerWebExchange exchange);}
KeyResolver接口允许使用可插拔策略来派生限制请求的key。在未来的里程碑版本中,将有一些KeyResolver实现。
KeyResolver的默认实现是PrincipalNameKeyResolver,它从ServerWebExchange检索Principal并调用Principal.getName()。 默认情况下,如果KeyResolver 没有获取到key,请求将被拒绝。此行为可以使用 spring.cloud.gateway.filter.request-rate-limiter.deny-empty-key (true or false) 和 spring.cloud.gateway.filter.request-rate-limiter.empty-key-status-code属性进行调整。 说明 无法通过"shortcut" 配置RequestRateLimiter。以下示例无效application.properties.
# INVALID SHORTCUT CONFIGURATIONspring.cloud.gateway.routes[0].filters[0]=RequestRateLimiter=2, 2, #{@userkeyresolver}
### 3.8.1 Redis RateLimiter
Redis的实现基于 Stripe实现。它需要使用spring-boot-starter-data-redis-reactive Spring Boot starter
。 使用的算法是Token Bucket Algorithm.。 redis-rate-limiter.replenishRate是你允许用户每秒执行多少请求,而丢弃任何请求。这是令牌桶的填充速率。
redis-rate-limiter.burstCapacity
是允许用户在一秒钟内执行的最大请求数。这是令牌桶可以保存的令牌数。将此值设置为零将阻止所有请求。
稳定速率是通过在replenishRate 和 burstCapacity中设置相同的值来实现的。可通过设置burstCapacity高于replenishRate来允许临时突发流浪。在这种情况下,限流器需要在两次突发之间留出一段时间(根据replenishRate),因为连续两次突发将导致请求丢失 (HTTP 429 - Too Many Requests).。
application.yml.
spring: cloud: gateway: routes: - id: requestratelimiter_route uri: http://example.org filters: - name: RequestRateLimiter args: redis-rate-limiter.replenishRate: 10 redis-rate-limiter.burstCapacity: 20
Config.java.
@BeanKeyResolver userKeyResolver() { return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("user"));}
这定义了每个用户10个请求的限制。允许20个突发,但下一秒只有10个请求可用。KeyResolver是一个简单的获取user请求参数的工具(注意:不建议用于生产)。
限流器也可以定义为RateLimiter接口的实现 bean。在配置中,按名称使用SpEL引用bean。#{@myRateLimiter}是引用名为’myRateLimiter’的bean的SpEL表达式。application.yml.
spring: cloud: gateway: routes: - id: requestratelimiter_route uri: http://example.org filters: - name: RequestRateLimiter args: rate-limiter: "#{@myRateLimiter}" key-resolver: "#{@userKeyResolver}"
该过滤器有一个 status 和一个 url参数。status是300类重定向HTTP代码,如301。该URL应为有效的URL,这将是 Location header的值。
application.yml.
spring: cloud: gateway: routes: - id: prefixpath_route uri: http://example.org filters: - RedirectTo=302, http://acme.org
这将发送一个302状态码和一个Location:http://acme.org header来执行重定向。
RemoveNonProxyHeaders GatewayFilter Factory 从转发请求中删除headers。删除的默认头列表来自 IETF.
The default removed headers are:
Connection
Keep-Alive Proxy-Authenticate Proxy-Authorization TE Trailer Transfer-Encoding Upgrade 要更改此设置,请将 spring.cloud.gateway.filter.remove-non-proxy-headers.headers属性设置为要删除的header名称。有一个name参数. 这是要删除的header的名称。
application.yml.
spring: cloud: gateway: routes: - id: removerequestheader_route uri: http://example.org filters: - RemoveRequestHeader=X-Request-Foo
这将在X-Request-Foo header被发送到下游之前删除它。
有一个name参数. 这是要删除的header的名称。
application.yml.
spring: cloud: gateway: routes: - id: removeresponseheader_route uri: http://example.org filters: - RemoveResponseHeader=X-Response-Foo
这将在返回到网关client之前从响应中删除x-response-foo头。
包含一个 regexp正则表达式参数和一个 replacement 参数. 通过使用Java正则表达式灵活地重写请求路径。
application.yml.
spring: cloud: gateway: routes: - id: rewritepath_route uri: http://example.org predicates: - Path=/foo/** filters: - RewritePath=/foo/(?.*), /$\{ segment}
对于请求路径/foo/bar,将在发出下游请求之前将路径设置为/bar。注意,由于YAML规范,请使用 $\替换 $。
包含 name, regexp和 replacement 参数.。通过使用Java正则表达式灵活地重写响应头的值。
application.yml.
spring: cloud: gateway: routes: - id: rewriteresponseheader_route uri: http://example.org filters: - RewriteResponseHeader=X-Response-Foo, , password=[^&]+, password=***
对于一个/42?user=ford&password=omg!what&flag=true的header值,在做下游请求时将被设置为/42?user=ford&password=***&flag=true,由于YAML规范,请使用 $\替换 $。
SaveSession GatewayFilter Factory将调用转发到下游之前强制执行WebSession::save 操作。这在使用 Spring Session 之类时特别有用,需要确保会话状态在进行转发调用之前已保存。
application.yml.
spring: cloud: gateway: routes: - id: save_session uri: http://example.org predicates: - Path=/foo/** filters: - SaveSession
如果你希望要将[Spring Security](https://projects.spring.io/Spring Security/)与Spring Session集成,并确保安全详细信息已转发到远程的进程,这一点至关重要。
SecureHeaders GatewayFilter Factory 将许多headers添加到reccomedation处的响应中,从this blog post.
添加以下标题(使用默认值分配):
X-Xss-Protection:1; mode=blockStrict-Transport-Security:max-age=631138519X-Frame-Options:DENYX-Content-Type-Options:nosniffReferrer-Policy:no-referrerContent-Security-Policy:default-src 'self' https:; font-src 'self' https: data:; img-src 'self' https: data:; object-src 'none'; script-src https:; style-src 'self' https: 'unsafe-inline'X-Download-Options:noopenX-Permitted-Cross-Domain-Policies:none
要更改默认值,请在spring.cloud.gateway.filter.secure-headers 命名空间中设置相应的属性:
Property to change:
xss-protection-headerstrict-transport-securityframe-optionscontent-type-optionsreferrer-policycontent-security-policydownload-optionspermitted-cross-domain-policies
SetPath GatewayFilter Factory 采用 template路径参数。它提供了一种通过允许路径的模板化segments来操作请求路径的简单方法。使用Spring Framework中的URI模板,允许多个匹配segments。
application.yml.
spring: cloud: gateway: routes: - id: setpath_route uri: http://example.org predicates: - Path=/foo/{segment} filters: - SetPath=/{segment}
对于一个 /foo/bar请求,在做下游请求前,路径将被设置为/bar
SetResponseHeader GatewayFilter Factory 包括 name 和 value 参数.
application.yml.
spring: cloud: gateway: routes: - id: setresponseheader_route uri: http://example.org filters: - SetResponseHeader=X-Response-Foo, Bar
此GatewayFilter使用给定的名称替换所有header,而不是添加。因此,如果下游服务器响应为X-Response-Foo:1234,则会将其替换为X-Response-Foo:Bar,这是网关客户端将接收的内容。
SetStatus GatewayFilter Factory 包括唯一的 status参数.必须是一个可用的Spring HttpStatus。它可以是整数值404或字符串枚举NOT_FOUND。
application.yml.
spring: cloud: gateway: routes: - id: setstatusstring_route uri: http://example.org filters: - SetStatus=BAD_REQUEST - id: setstatusint_route uri: http://example.org filters: - SetStatus=401
在这个例子中,HTTP返回码将设置为401.
StripPrefix GatewayFilter Factory 包括一个parts参数。 parts参数指示在将请求发送到下游之前,要从请求中去除的路径中的节数。
application.yml.
spring: cloud: gateway: routes: - id: nameRoot uri: http://nameservice predicates: - Path=/name/** filters: - StripPrefix=2
当通过网关发出/name/bar/foo请求时,向nameservice发出的请求将是http://nameservice/foo。
Retry GatewayFilter Factory包括 retries, statuses, methods和 series 参数.
retries: 应尝试的重试次数
statuses: 应该重试的HTTP状态代码,用org.springframework.http.HttpStatus标识 methods: 应该重试的HTTP方法,用 org.springframework.http.HttpMethod标识 series: 要重试的一系列状态码,用 org.springframework.http.HttpStatus.Series标识 application.yml.spring: cloud: gateway: routes: - id: retry_test uri: http://localhost:8080/flakey predicates: - Host=*.retry.com filters: - name: Retry args: retries: 3 statuses: BAD_GATEWAY
注意
retry filter 不支持body请求的重试,如通过body的POST 或 PUT请求注意
在使用带有前缀为 forward: 的retry filter时,应仔细编写目标端点,以便在出现错误时不会执行任何可能导致将响应发送到客户端并提交的操作。例如,如果目标端点是带注解的controller,则目标controller方法不应返回带有错误状态代码的ResponseEntity。相反,它应该抛出一个Exception,或者发出一个错误信号,例如通过Mono.error(ex) 返回值,重试过滤器可以配置为通过重试来处理。当请求大小大于允许的限制时,RequestSize GatewayFilter Factory可以限制请求不到达下游服务。过滤器以RequestSize作为参数,这是定义请求的允许大小限制(以字节为单位)。
application.yml.
spring: cloud: gateway: routes: - id: request_size_route uri: http://localhost:8080/upload predicates: - Path=/upload filters: - name: RequestSize args: maxSize: 5000000
当请求因大小而被拒绝时, RequestSize GatewayFilter Factory 将响应状态设置为413 Payload Too Large,并带有额外的header errorMessage 。下面是一个 errorMessage的例子。
errorMessage : Request size is larger than permissible limit. Request size is 6.0 MB where permissible limit is 5.0 MB
注意
如果未在路由定义中作为filter参数提供,则默认请求大小将设置为5 MB。这个过滤器被定义为beta版本,将来API可能会改变。
此过滤器可用于在请求主体被网关发送到下游之前对其进行修改。
注意
只能使用Java DSL配置此过滤器@Beanpublic RouteLocator routes(RouteLocatorBuilder builder) { return builder.routes() .route("rewrite_request_obj", r -> r.host("*.rewriterequestobj.org") .filters(f -> f.prefixPath("/httpbin") .modifyRequestBody(String.class, Hello.class, MediaType.APPLICATION_JSON_VALUE, (exchange, s) -> return Mono.just(new Hello(s.toUpperCase())))).uri(uri)) .build();}static class Hello { String message; public Hello() { } public Hello(String message) { this.message = message; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; }}
这个过滤器被定义为beta版本,将来API可能会改变。
此过滤器可用于在将响应正文发送回客户端之前对其进行修改。注意
只能使用Java DSL配置此过滤器@Beanpublic RouteLocator routes(RouteLocatorBuilder builder) { return builder.routes() .route("rewrite_response_upper", r -> r.host("*.rewriteresponseupper.org") .filters(f -> f.prefixPath("/httpbin") .modifyResponseBody(String.class, String.class, (exchange, s) -> Mono.just(s.toUpperCase()))).uri(uri) .build();}
GlobalFilter接口与GatewayFilter具有相同的签名。是有条件地应用于所有路由的特殊过滤器。(此接口和用法可能在将来的里程碑版本中发生更改)。
当请求进入(并与路由匹配)时,筛选Web Handler 会将GlobalFilter的所有实例和所有的GatewayFilter路由特定实例添加到 filter chain。filter组合的排序由org.springframework.core.Ordered接口决定,可以通过实现getOrde()方法或使用@Order注释来设置。
由于Spring Cloud Gateway将用于执行过滤器逻辑区分为“前置”和“后置”阶段,具有最高优先级的过滤器将是“前置”阶段的第一个,而“后置”阶段的最后一个。 ExampleConfiguration.java.@Bean@Order(-1)public GlobalFilter a() { return (exchange, chain) -> { log.info("first pre filter"); return chain.filter(exchange).then(Mono.fromRunnable(() -> { log.info("third post filter"); })); };}@Bean@Order(0)public GlobalFilter b() { return (exchange, chain) -> { log.info("second pre filter"); return chain.filter(exchange).then(Mono.fromRunnable(() -> { log.info("second post filter"); })); };}@Bean@Order(1)public GlobalFilter c() { return (exchange, chain) -> { log.info("third pre filter"); return chain.filter(exchange).then(Mono.fromRunnable(() -> { log.info("first post filter"); })); };}
ForwardRoutingFilter在exchange属性ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR中查找URI。如果URL有一个forwardscheme (如 forward:///localendpoint),它将使用Spring DispatcherHandler 来处理请求。请求URL的路径部分将被转发URL中的路径覆盖。未修改的原始URL将附加到 ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR属性中的列表中。
LoadBalancerClientFilter在exchange属性ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR中查找URI。如果URL有一个lbscheme (如 lb://myservice),它将使用Spring Cloud LoadBalancerClient 将名称(在前一个示例中为’myservice)解析为实际主机和端口,并替换URI。未修改的原始URL将附加到ServerWebExchangeUtils.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/**
注意
默认情况下,如果一个服务实例在LoadBalancer 中没有发现,则返回503。可以通过设置spring.cloud.gateway.loadbalancer.use404=true来让网管返回404. 从LoadBalancer返回的ServiceInstance的isSecure 值将覆盖在对网关发出的请求中指定的scheme。例如,如果请求通过HTTPS进入网关,但ServiceInstance表示它不安全,则下游请求将通过HTTP协议。相反的情况也适用。但是,如果在网关配置中为路由指定了GATEWAY_SCHEME_PREFIX_ATTR,则前缀将被删除,并且路由URL生成的scheme将覆盖ServiceInstance配置。如果位于 ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR属性中的URL具有http 或https 模式,则会运行Netty Routing Filter。它使用Netty HttpClient 发出下游代理请求。响应放在 ServerWebExchangeUtils.CLIENT_RESPONSE_ATTR exchange属性中,以便在以后的过滤器中使用。(有一个实验阶段不需要Netty的相同的功能的Filter,WebClientHttpRoutingFilter)
如果ServerWebExchangeUtils.CLIENT_RESPONSE_ATTR exchange属性中存在 Netty HttpClientResponse,则运行 NettyWriteResponseFilter 。它在其他所有过滤器完成后将代理响应写回网关客户端响应之后运行。(有一个不需要netty的实验性的WebClientWriteResponseFilter执行相同的功能)
如果ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR exchange属性中存在Route对象,RouteToRequestUrlFilter将运行。它基于请求URI创建一个新的URI,使用Route对象的uri属性进行更新。新的URI被放置在ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR exchange属性中。
如果该URI有一个前缀scheme,例如lb:ws://serviceid,则会从该URI中剥离该 lb scheme,并将其放置在ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR中,以便稍后在过滤器链中使用。如果ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTRexchange属性中有 ws 、 wssscheme,则Websocket Routing Filter将被运行。它使用Spring Web Socket基础模块将Websocket转发到下游。
URI前缀为lb的Websockets可以被负载均衡,如 lb:ws://serviceid. 注意 如果使用 SockJS 作为普通HTTP的fallback,则应配置普通HTTP路由以及WebSocket路由。application.yml.
spring: cloud: gateway: routes: # SockJS route - id: websocket_sockjs_route uri: http://localhost:3001 predicates: - Path=/websocket/info/** # Normwal Websocket route - id: websocket_route uri: ws://localhost:3001 predicates: - Path=/websocket/**
要启用网关指标,请将spring-boot-starter-actuator添加为项目依赖项。然后,默认情况下,只要属性spring.cloud.gateway.metrics.enabled未设置为false,网关指标过滤器就会运行。此过滤器添加名为“gateway.requests”的计时器指标,并带有以下标记:
routeId: The route id routeUri: API 将被转发的URI outcome: 结果分类依据 HttpStatus.Series status: 返回client的请求的Http Status
这些指标可以从/actuator/metrics/gateway.requests中获取,可以很容易地与Prometheus集成以创建Grafana dashboard.
注意 要将pometheus启用,需要添加 micrometer-registry-prometheus为项目依赖。网关路由ServerWebExchange之后,它将通过向Exchange属性添加gatewayAlreadyRouted,将该exchange标记为“routed”。一旦一个请求被标记为routed,其他路由过滤器将不会再次路由该请求,将跳过该过滤器。有一些方便的方法可以用来将exchange标记为routed,或者检查exchange是否已经routed。
ServerWebExchangeUtils.isAlreadyRouted 有一个 ServerWebExchange对象并检查它是否已"routed" ServerWebExchangeUtils.setAlreadyRouted 有一个 ServerWebExchange 对象并将其标记为"routed"
网关可以通过常规的 Spring server configuration 来侦听HTTPS上的请求。例子:
application.yml.
server: ssl: enabled: true key-alias: scg key-store-password: scg1234 key-store: classpath:scg-keystore.p12 key-store-type: PKCS12
网关路由可以路由到HTTP和HTTPS后端。如果路由到HTTPS后端,则可以将网关配置为信任所有具有证书的下游服务:
application.yml.
spring: cloud: gateway: httpclient: ssl: useInsecureTrustManager: true
不建议在生产环境使用不安全的信任管理器。对于生产部署,可以使用一组已知证书配置网关,这些证书可以通过以下方式进行配置:
application.yml.
spring: cloud: gateway: httpclient: ssl: trustedX509Certificates: - cert1.pem - cert2.pem
如果Spring Cloud Gateway未配置受信任证书,则使用默认信任库(可以使用系统属性javax.net.ssl.trustStore覆盖)。
网关维护一个用于路由到后端的client池。当通过HTTPS通信时,客户端启动一个TLS握手,其中可能会有很多超时。这些超时可以这样配置(显示默认值):
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的集合驱动。
RouteDefinitionLocator.java.
public interface RouteDefinitionLocator { FluxgetRouteDefinitions();}
默认情况下,PropertiesRouteDefinitionLocator使用Spring Boot的@ConfigurationProperties机制加载属性。
以下两个示例是等效的:
application.yml.
spring: cloud: gateway: routes: - id: setstatus_route uri: http://example.org filters: - name: SetStatus args: status: 401 - id: setstatusshortcut_route uri: http://example.org filters: - SetStatus=401
对于网关的大部分用法,配置文件方式是够用的,但一些生产用例更建议从外部源(如数据库)加载配置。未来的里程碑版本将有基于Spring Data Repositories (如Redis、MongoDB和Cassandra)的RouteDefinitionLocator实现。
为了可以更简单在Java中配置,在RouteLocatorBuilder bean中定义了一个fluent API。
GatewaySampleApplication.java.
// static imports from GatewayFilters and RoutePredicates@Beanpublic 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") ) .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") ) .build();}
这种样式还允许使用更多的自定义断言。由RouteDefinitionLocator beans定义的断言使用逻辑 and组合。通过使用fluent Java API,可以在 Predicate类上使用 and()、or() 、 negate()运算符。
可以将网关配置为基于使用兼容DiscoveryClient注册中心注册的服务来创建路由。
要启用此功能,请设置spring.cloud.gateway.discovery.locator.enabled=true,并确保DiscoveryClient实现位于classpath上并已启用(如netflix eureka、consul或zookeeper)。
默认情况下,网关为通过DiscoveryClient创建的路由定义单个断言和过滤器。
默认断言是使用/serviceId/**定义的path断言,其中serviceId是DiscoveryClient中服务的ID。 默认过滤器是使用正则表达式 /serviceId/(?.*)和替换的/${remaining}进行重写。这只是在请求被发送到下游之前从路径中截取掉 service id 。 可以通过设置spring.cloud.gateway.discovery.locator.predicates[x] and spring.cloud.gateway.discovery.locator.filters[y]来实现自定义DiscoveryClient路由使用的断言and/or过滤器。当你这样做时,如果你想要保留这个功能,你需要确保包括上面的默认断言和过滤器。下面是这样一个例子。application.properties.
spring.cloud.gateway.discovery.locator.predicates[0].name: Pathspring.cloud.gateway.discovery.locator.predicates[0].args[pattern]: "'/'+serviceId+'/**'"spring.cloud.gateway.discovery.locator.predicates[1].name: Hostspring.cloud.gateway.discovery.locator.predicates[1].args[pattern]: "'**.foo.com'"spring.cloud.gateway.discovery.locator.filters[0].name: Hystrixspring.cloud.gateway.discovery.locator.filters[0].args[name]: serviceIdspring.cloud.gateway.discovery.locator.filters[1].name: RewritePathspring.cloud.gateway.discovery.locator.filters[1].args[regexp]: "'/' + serviceId + '/(?.*)'"spring.cloud.gateway.discovery.locator.filters[1].args[replacement]: "'/${remaining}'"
设置 -Dreactor.netty.http.server.accessLogEnabled=true 来开启Reactor Netty access logs,注意必须是Java System Property而不是Spring Boot property。
logging 模块也可以通过配置单独输出一个access log文件,下面是logback的配置例子:
logback.xml.
access_log.log %msg%n
我们可以通过配置网关来控制CORS行为,全局CORS配置是 Spring Framework CorsConfiguration模式的URL MAP。
application.yml.
spring: cloud: gateway: globalcors: corsConfigurations: '[/**]': allowedOrigins: "http://docs.spring.io" allowedMethods: - GET
例子中将允许从docs.spring.io发出的所有GET请求进行CORS请求。
/gateway的actuator端点允许监视Spring Cloud Gateway应用程序并与之交互。要进行远程访问,必须在应用程序属性中暴露HTTP或JMX 端口。
application.properties.
management.endpoint.gateway.enabled=true # default valuemanagement.endpoints.web.exposure.include=gateway
要检索应用于所有路由的 [global filters],请get请求 /actuator/gateway/globalfilters。返回的结果类似于以下内容:
{ "org.springframework.cloud.gateway.filter.LoadBalancerClientFilter@77856cc5": 10100, "org.springframework.cloud.gateway.filter.RouteToRequestUrlFilter@4f6fd101": 10000, "org.springframework.cloud.gateway.filter.NettyWriteResponseFilter@32d22650": -1, "org.springframework.cloud.gateway.filter.ForwardRoutingFilter@106459d9": 2147483647, "org.springframework.cloud.gateway.filter.NettyRoutingFilter@1fbd5e0": 2147483647, "org.springframework.cloud.gateway.filter.ForwardPathFilter@33a71d23": 0, "org.springframework.cloud.gateway.filter.AdaptCachedBodyGlobalFilter@135064ea": 2147483637, "org.springframework.cloud.gateway.filter.WebsocketRoutingFilter@23c05889": 2147483646}
返回结果包含已就绪的global filters的详细信息(如 org.springframework.cloud.gateway.filter.LoadBalancerClientFilter@77856cc5
)。对于每个global filters,返回结果字符串对应过滤器链中的相应顺序。
要检索应用于路由的 [GatewayFilter factories] ,请get请求/actuator/gateway/routefilters。返回结果类似于以下内容:
{ "[AddRequestHeaderGatewayFilterFactory@570ed9c configClass = AbstractNameValueGatewayFilterFactory.NameValueConfig]": null, "[SecureHeadersGatewayFilterFactory@fceab5d configClass = Object]": null, "[SaveSessionGatewayFilterFactory@4449b273 configClass = Object]": null}
返回结果包含应用于所有路由的GatewayFilter的详细信息。显示每个工厂提供字符串格式的相应对象(例如, [SecureHeadersGatewayFilterFactory@fceab5d configClass = Object]
)。请注意,null值是由于endpoint controller实现不完整造成的,因为它尝试在filter chain中设置对象的顺序,这不适用于GatewayFilter工厂对象。
如果要清理路由的缓存,请POST请求/actuator/gateway/refresh。该请求将返回一个没有body的200返回码。
要检索网关中定义的路由,发送GET请求/actuator/gateway/routes,返回结果如下所示:
[{ "route_id": "first_route", "route_object": { "predicate": "org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory$$Lambda$432/1736826640@1e9d7e7d", "filters": [ "OrderedGatewayFilter{delegate=org.springframework.cloud.gateway.filter.factory.PreserveHostHeaderGatewayFilterFactory$$Lambda$436/674480275@6631ef72, order=0}" ] }, "order": 0},{ "route_id": "second_route", "route_object": { "predicate": "org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory$$Lambda$432/1736826640@cd8d298", "filters": [] }, "order": 0}]
返回结果中包含网关中所有定义的路由信息,下面表格中描述了返回结果信息:
要获取单个路由的信息,发送GET请求 /actuator/gateway/routes/{id} (如: /actuator/gateway/routes/first_route),返回结果如下所示:
{ "id": "first_route", "predicates": [{ "name": "Path", "args": {"_genkey_0":"/first"} }], "filters": [], "uri": "http://www.uri-destination.org", "order": 0}]
要创建一个路由,发送POST请求 /gateway/routes/{id_route_to_create},参数为JSON结构,具体参数数据结构参考上面章节。
要删除一个路由,发送 DELETE请求 /gateway/routes/{id_route_to_delete}。
下表总结了Spring Cloud Gateway actuator endpoints。注意,每个endpoint都是/actuator/gateway作为基本路径。
转载地址:http://smtuf.baihongyu.com/