【Spring Gateway】 全局过滤器

Metadata

title: 【Spring Gateway】 全局过滤器
date: 2023-02-14 09:35
tags:
  - 行动阶段/完成
  - 主题场景/组件
  - 笔记空间/KnowladgeSpace/ProgramSpace/ModuleSpace
  - 细化主题/Module/SpringGateway
categories:
  - SpringGateway
keywords:
  - SpringGateway
description: 【Spring Gateway】 全局过滤器

【Spring Gateway】 全局过滤器

GlobalFilter接口具有与GatewayFilter相同的签名。这些是特殊的过滤器,有条件地应用于所有路由。

Combined Global Filter and GatewayFilter Ordering | 组合全局过滤器和网关过滤器排序

当请求与路由匹配时,过滤web处理程序将GlobalFilter的所有实例和GatewayFilter的所有路由特定实例添加到过滤器链中。这个组合过滤器链由org.springframework.core.Ordered接口排序,您可以通过实现getOrder()方法来设置该接口。

Spring Cloud Gateway区分了过滤器逻辑执行的“前”和“后”阶段(参见它是如何工作的),具有最高优先级的过滤器是“前”阶段的第一个和“后”阶段的最后一个。

下面的清单配置了一个过滤器链:

@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;
    }
}

Forward Routing Filter | 转发路由过滤器

ForwardRoutingFilter在交换属性ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR中查找URI。如果URL有转发模式(比如forward:///localendpoint),它会使用Spring DispatcherHandler来处理请求。请求URL的路径部分将被转发URL中的路径覆盖。未修改的原始URL被追加到ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR中的列表中。

ReactiveLoadBalancerClientFilter

ReactiveLoadBalancerClientFilter在名为ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR的exchange属性中查找URI。如果URL具有lb模式(例如lb://myservice),它会使用Spring Cloud ReactorLoadBalancer将名称(在本例中是myservice)解析为实际的主机和端口,并替换相同属性中的URI。未修改的原始URL被附加到ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR中的列表中。过滤器还在ServerWebExchangeUtils中查找。GATEWAY_SCHEME_PREFIX_ATTR属性,查看它是否等于lb。如果等于,则应用相同的规则。下面的代码清单配置了ReactiveLoadBalancerClientFilter:

spring:
  cloud:
    gateway:
      routes:
      - id: myRoute
        uri: lb://service
        predicates:
        - Path=/service/**

The Netty Routing Filter | Netty路由过滤器

如果URL位于ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR交换属性具有http或https方案, Netty路由过滤器将运行。它使用Netty HttpClient进行下游代理请求。响应放在ServerWebExchangeUtils.CLIENT_RESPONSE_ATTR中。以便在以后的过滤器中使用。(还有一个实验性的WebClientHttpRoutingFilter,它可以执行相同的功能,但不需要Netty。)

The Netty Write Response Filter | Netty写响应过滤器

如果ServerWebExchangeUtils中有Netty HttpClientResponse, NettyWriteResponseFilter将运行。CLIENT_RESPONSE_ATTR交换属性。它在所有其他过滤器完成后运行,并将代理响应写回网关客户机响应。(还有一个实验性的WebClientWriteResponseFilter,它可以执行相同的功能,但不需要Netty。)

The RouteToRequestUrl Filter | RouteToRequestUrl过滤器

如果ServerWebExchangeUtils中存在Route对象。GATEWAY_ROUTE_ATTR交换属性,RouteToRequestUrlFilter运行。它创建一个基于请求URI的新URI,但使用Route对象的URI属性进行更新。新的URI被放置在ServerWebExchangeUtils中。GATEWAY_REQUEST_URL_ATTR交换属性。

如果URI有一个方案前缀,例如lb:ws://serviceid,则将lb方案从URI中剥离,放在ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR中。以便稍后在过滤器链中使用。

The Websocket Routing Filter | Websocket路由过滤器

如果URL位于 ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR 交换属性有ws或wss方案,websocket路由过滤器运行。它使用Spring WebSocket基础设施向下游转发WebSocket请求。

你可以通过在URI前面加上lb来平衡websockets的负载,比如lb:ws://serviceid

下面的清单配置了一个websocket路由过滤器:

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/**

The Gateway Metrics Filter | 网关指标过滤器

要启用网关度量,将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中获取这些指标。请求,并且可以很容易地与Prometheus集成以创建Grafana仪表板。

Marking An Exchange As Routed | 将交换机标记为路由

在网关路由了一个ServerWebExchange之后,它通过将gatewayalreadyrouting添加到交换属性中将该交换标记为“路由”。一旦一个请求被标记为路由,其他路由筛选器将不会再次路由该请求,基本上跳过筛选器。您可以使用一些方便的方法将交换机标记为路由或检查交换机是否已经路由。

  • ServerWebExchangeUtils.isAlreadyRouted接受一个ServerWebExchange对象,并检查它是否已被“路由”。
  • ServerWebExchangeUtils.setAlreadyRouted接受一个ServerWebExchange对象,并将其标记为“路由”。