本文已参与「新人创作礼」活动,一起开启掘金创作之路。
Spring Cloud Gateway
3.1.0
7.全局过滤器
该GlobalFilter接口具有与 相同的签名GatewayFilter。这些是有条件地应用于所有路由的特殊过滤器。
此接口及其用法可能会在未来的里程碑版本中发生变化。
7.1.组合全局过滤器和GatewayFilter排序
当请求与路由匹配时,过滤 Web 处理程序会将 的所有实例GlobalFilter和所有特定于路由的实例添加GatewayFilter到过滤器链中。这个组合的过滤器链是按org.springframework.core.Ordered接口排序的,你可以通过实现getOrder()方法来设置。
由于 Spring Cloud Gateway 区分过滤器逻辑执行的“前”和“后”阶段(请参阅它的工作原理),具有最高优先级的过滤器是“前”阶段的第一个和“后”阶段的最后一个 -阶段。
以下清单配置了一个过滤器链:
例 57.ExampleConfiguration.java
@Bean
public GlobalFilter customFilter() {
return new CustomGlobalFilter();
}
public class CustomGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info("custom global filter");
return chain.filter(exchange);
}
@Override
public int getOrder() {
return -1;
}
}
7.2. 转发路由过滤器
在ForwardRoutingFilterexchange 属性中查找 URI ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR。如果 URL 有一个forward方案(例如forward:///localendpoint),它使用 SpringDispatcherHandler来处理请求。请求 URL 的路径部分被转发 URL 中的路径覆盖。未修改的原始 URL 将附加到ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR属性中的列表中。
7.3. 这ReactiveLoadBalancerClientFilter
在ReactiveLoadBalancerClientFilter名为 的交换属性中查找 URI ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR。如果 URL 有一个lb方案(例如lb://myservice),它使用 Spring CloudReactorLoadBalancer将名称(在本例中)解析为myservice实际的主机和端口,并替换同一属性中的 URI。未修改的原始 URL 将附加到ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR属性中的列表中。过滤器还查看ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR属性以查看它是否等于lb。如果是这样,则适用相同的规则。以下清单配置了一个ReactiveLoadBalancerClientFilter:
示例 58.application.yml
spring:
cloud:
gateway:
routes:
- id: myRoute
uri: lb://service
predicates:
- Path=/service/**
默认情况下,当 找不到服务实例时ReactorLoadBalancer,503返回 a。404您可以通过设置将网关配置为返回spring.cloud.gateway.loadbalancer.use404=true。
从返回 的isSecure值覆盖向网关发出的请求中指定的方案。例如,如果请求通过网关进入,但指示它不安全,则发出下游请求。相反的情况也可以适用。但是,如果在网关配置中为路由指定了前缀,则会去除前缀,并且路由 URL 的结果方案会覆盖配置。
ServiceInstanceReactiveLoadBalancerClientFilterHTTPSServiceInstanceHTTPGATEWAY_SCHEME_PREFIX_ATTRServiceInstance
Gateway 支持所有 LoadBalancer 功能。您可以在Spring Cloud Commons 文档中阅读有关它们的更多信息。
7.4. Netty 路由过滤器
如果位于ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR交换属性中的 URL 具有httporhttps方案,则 Netty 路由过滤器运行。它使用 NettyHttpClient发出下游代理请求。响应被放入ServerWebExchangeUtils.CLIENT_RESPONSE_ATTR交换属性中,以供稍后的过滤器使用。(还有一个WebClientHttpRoutingFilter执行相同功能但不需要 Netty 的实验。)
7.5. Netty 写响应过滤器
如果交换属性中NettyWriteResponseFilter有 Netty HttpClientResponse,则运行。ServerWebExchangeUtils.CLIENT_RESPONSE_ATTR它在所有其他过滤器完成后运行,并将代理响应写回网关客户端响应。(还有一个WebClientWriteResponseFilter执行相同功能但不需要 Netty 的实验。)
7.6. RouteToRequestUrl过滤器
如果交换属性中有Route对象,则运行。它基于请求 URI 创建一个新的 URI,但使用对象的 URI 属性进行更新。新的 URI 被放置在exchange 属性中。ServerWebExchangeUtils.GATEWAY_ROUTE_ATTRRouteToRequestUrlFilterRouteServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR
如果 URI 具有方案前缀,例如lb:ws://serviceid,lb则从 URI 中剥离方案并放置在ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR过滤器链中以供稍后使用。
7.7. Websocket 路由过滤器
如果位于ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTRexchange 属性中的 URL 具有wsorwss方案,则 websocket 路由过滤器运行。它使用 Spring WebSocket 基础设施向下游转发 websocket 请求。
您可以通过在 URI 前加上前缀来负载平衡 websocket lb,例如lb:ws://serviceid.
如果你使用SockJS作为普通 HTTP 的后备,你应该配置一个普通的 HTTP 路由以及 websocket 路由。
以下清单配置了一个 websocket 路由过滤器:
示例 59.application.yml
spring:
cloud:
gateway:
routes:
# SockJS route
- id: websocket_sockjs_route
uri: http://localhost:3001
predicates:
- Path=/websocket/info/**
# Normal Websocket route
- id: websocket_route
uri: ws://localhost:3001
predicates:
- Path=/websocket/**
7.8. 网关指标过滤器
要启用网关指标,请将 spring-boot-starter-actuator 添加为项目依赖项。然后,默认情况下,只要该属性spring.cloud.gateway.metrics.enabled未设置为,网关指标过滤器就会运行false。spring.cloud.gateway.requests此过滤器添加一个使用以下标签命名的计时器指标:
- routeId: 路由ID。
- routeUri:API 路由到的 URI。
- outcome:结果,按HttpStatus.Series分类。
- status:返回给客户端的请求的HTTP状态。
- httpStatusCode:返回给客户端的请求的 HTTP 状态。
- httpMethod:用于请求的 HTTP 方法。
此外,通过该属性spring.cloud.gateway.metrics.tags.path.enabled(默认设置为 false),您可以使用标签激活额外的指标:
- path:请求的路径。
然后可以从这些指标中提取/actuator/metrics/spring.cloud.gateway.requests并轻松与 Prometheus 集成以创建Grafana 仪表板。
要启用 prometheus 端点,请添加micrometer-registry-prometheus为项目依赖项。
7.9。将交换标记为已路由
网关路由 a 后,它通过添加 交换属性将该交换ServerWebExchange标记为“已路由” 。gatewayAlreadyRouted一旦请求被标记为已路由,其他路由过滤器将不会再次路由该请求,实质上是跳过过滤器。您可以使用一些便捷的方法将交换标记为已路由或检查交换是否已被路由。
-
ServerWebExchangeUtils.isAlreadyRouted获取一个ServerWebExchange对象并检查它是否已被“路由”。
-
ServerWebExchangeUtils.setAlreadyRouted获取一个ServerWebExchange对象并将其标记为“已路由”。
8. HttpHeadersFilters
HttpHeadersFilters 在将请求发送到下游之前应用于请求,例如在NettyRoutingFilter.
8.1。转发标头过滤器
标Forwarded头过滤器创建一个Forwarded标头以发送到下游服务。它将Host当前请求的标头、方案和端口添加到任何现有Forwarded标头。
8.2. RemoveHopByHop 标头过滤器
标RemoveHopByHop头过滤器从转发的请求中删除标头。删除的默认标头列表来自IETF。
默认删除的标题是:
- 联系
- 活着
- 代理验证
- 代理授权
- TE
- 预告片
- 传输编码
- 升级
要更改此设置,请将spring.cloud.gateway.filter.remove-hop-by-hop.headers属性设置为要删除的标头名称列表。
8.3. XForwarded 标头过滤器
标XForwarded头过滤器创建各种X-Forwarded-*标头以发送到下游服务。它使用Host当前请求的标头、方案、端口和路径来创建各种标头。
可以通过以下布尔属性控制单个标题的创建(默认为 true):
-
spring.cloud.gateway.x-forwarded.for-enabled
-
spring.cloud.gateway.x-forwarded.host-enabled
-
spring.cloud.gateway.x-forwarded.port-enabled
-
spring.cloud.gateway.x-forwarded.proto-enabled
-
spring.cloud.gateway.x-forwarded.prefix-enabled
附加多个标题可以由以下布尔属性控制(默认为 true):
-
spring.cloud.gateway.x-forwarded.for-append
-
spring.cloud.gateway.x-forwarded.host-append
-
spring.cloud.gateway.x-forwarded.port-append
-
spring.cloud.gateway.x-forwarded.proto-append
-
spring.cloud.gateway.x-forwarded.prefix-append
9. TLS 和 SSL
网关可以通过遵循通常的 Spring 服务器配置来监听 HTTPS 上的请求。以下示例显示了如何执行此操作:
例 60.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 后端,则可以使用以下配置将网关配置为信任所有下游证书:
示例 61.application.yml
spring:
cloud:
gateway:
httpclient:
ssl:
useInsecureTrustManager: true
使用不安全的信任管理器不适合生产。对于生产部署,您可以使用一组已知证书配置网关,它可以使用以下配置信任这些证书:
示例 62.application.yml
spring:
cloud:
gateway:
httpclient:
ssl:
trustedX509Certificates:
- cert1.pem
- cert2.pem
如果 Spring Cloud Gateway 没有配置受信任的证书,则使用默认的信任存储(您可以通过设置javax.net.ssl.trustStore系统属性来覆盖它)。
9.1.TLS 握手
网关维护一个客户端池,用于路由到后端。通过 HTTPS 进行通信时,客户端会启动 TLS 握手。许多超时与此握手相关。您可以配置这些超时,可以按如下方式配置(显示默认值):
示例 63.application.yml
spring:
cloud:
gateway:
httpclient:
ssl:
handshake-timeout-millis: 10000
close-notify-flush-timeout-millis: 3000
close-notify-read-timeout-millis: 0
10. 配置
Spring Cloud Gateway 的配置由RouteDefinitionLocator实例集合驱动。以下清单显示了RouteDefinitionLocator接口的定义:
示例 64.RouteDefinitionLocator.java
public interface RouteDefinitionLocator {
Flux<RouteDefinition> getRouteDefinitions();
}
默认情况下,aPropertiesRouteDefinitionLocator使用 Spring Boot 的@ConfigurationProperties机制加载属性。
早期的配置示例都使用使用位置参数而不是命名参数的快捷表示法。下面两个例子是等价的:
示例 65.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
对于网关的某些用途,属性就足够了,但某些生产用例受益于从外部源(例如数据库)加载配置。未来的里程碑版本将具有RouteDefinitionLocator基于 Spring Data Repositories 的实现,例如 Redis、MongoDB 和 Cassandra。
10.1。RouteDefinition 指标 要启用RouteDefinition指标,请将 spring-boot-starter-actuator 添加为项目依赖项。然后,默认情况下,只要该属性spring.cloud.gateway.metrics.enabled设置为,这些指标就可用true。将添加一个名为的量规度量spring.cloud.gateway.routes.count,其值为RouteDefinitions. 该指标可从/actuator/metrics/spring.cloud.gateway.routes.count.
- 路由元数据配置 您可以使用元数据为每个路由配置附加参数,如下所示:
示例 66.application.yml
spring:
cloud:
gateway:
routes:
- id: route_with_metadata
uri: https://example.org
metadata:
optionName: "OptionValue"
compositeObject:
name: "value"
iAmNumber: 1
您可以从交换中获取所有元数据属性,如下所示:
Route route = exchange.getAttribute(GATEWAY_ROUTE_ATTR);
// get all metadata properties
route.getMetadata();
// get a single metadata property
route.getMetadata(someKey);