【深入解析spring cloud gateway】04 Global Filters

上一节学习了GatewayFilter。

回忆一下一个关键点:
GateWayFilterFactory的本质就是:针对配置进行解析,为指定的路由,添加Filter,以便对请求报文进行处理。

一、原理分析

GlobalFilter又是啥?先看一下接口定义

java 复制代码
public interface GlobalFilter {
    Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain);
}

再看一下GatewayFilter

java 复制代码
public interface GatewayFilter extends ShortcutConfigurable {
    Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain);
}

可以看到GatewayFilter和GlobalFilter方法签名是一模一样的,那为啥又要整一个GlobalFilter出来?

GatewayFilter的作用主要是,基于配置文件或者代码,就是routes那个配置,解析出配置,然后进行报文处理。这个Filter是跟某个route强行绑定的。

GlobalFilter,是直接强制加载的,不属于某个指定的route。而这个filter需不需要处理,是通过在filter方法中来进行判断的。如果不需要自己处理,就直接丢给链条中下个filter。

请求的处理逻辑,可以看以下代码

FilteringWebHandler.java

java 复制代码
@Override
public Mono<Void> handle(ServerWebExchange exchange) {
    Route route = exchange.getRequiredAttribute(GATEWAY_ROUTE_ATTR);
    List<GatewayFilter> gatewayFilters = route.getFilters();

    List<GatewayFilter> combined = new ArrayList<>(this.globalFilters);
    combined.addAll(gatewayFilters);
    // TODO: needed or cached?
    AnnotationAwareOrderComparator.sort(combined);

    if (logger.isDebugEnabled()) {
        logger.debug("Sorted gatewayFilterFactories: " + combined);
    }

    return new DefaultGatewayFilterChain(combined).filter(exchange);
}

代码解析:

  • 从配置中获取route,并取出满足当前route条件的gatewayFilter
  • GlobalFilter和gatewayFilter合并成一个list,并排序
  • filter封装成链,链式处理当前请求

二、如何自定义一个GlobalFilter

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

三、内置的GlobalFilter

3.1 Forward Routing Filter

处理URL格式为:forward:///localendpoint,这种将会被转发到forward后面的地址

3.2 The LoadBalancerClient Filter

没看到源码,本地是 SpringCloud 2021.0.1版本

3.3 The ReactiveLoadBalancerClientFilter

如果URL有⼀个 lb scheme (如 lb://myservice ),它将使⽤Spring Cloud ReactorLoadBalancer 将名称(在前⼀个示例中为 myservice )解析为实际主机和端⼝,并替换URI

yaml 复制代码
spring:
  cloud:
    gateway:
      routes:
      - id: myRoute
        uri: lb://service
        predicates:
        - Path=/service/**

3.4 The Netty Routing Filter

如果URL具有http 或https 模式,则会运⾏Netty Routing Filter。它使⽤Netty HttpClient 发出下游代理请求。

响应放在ServerWebExchangeUtils.CLIENT_RESPONSE_ATTR exchange属性中。

3.5 The Netty Write Response Filter

从ServerWebExchangeUtils.CLIENT_RESPONSE_ATTR exchange属性如果有值,此filter就执行,用于写响应报文到缓存。

3.6 The RouteToRequestUrl Filter

如果 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 中,以便稍后在过滤器链中使⽤。

3.7 The Websocket Routing Filter

如果 ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR exchange属性中有 ws 、 wss scheme,则Websocket Routing Filter将被运⾏。它使⽤Spring Web Socket基础模块将Websocket转发到下游。

URI前缀为 lb 的Websockets可以被负载均衡,如 lb:ws://serviceid

yaml 复制代码
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/**

3.8 The Gateway Metrics Filter

要启⽤⽹关指标,请将 spring-boot-starter-actuator 添加为项⽬依赖项。然后,默认情况下,只要属性 spring.cloud.gateway.metrics.enabled 未设置为 false ,⽹关指标过滤器就会运⾏。此过滤器添加名为 spring.cloud.gateway.requests 的计时器指标,并带有以下标记

  • routeId: route ID.
  • routeUri: API 将被转发的URI
  • outcome: 结果分类,依据 HttpStatus.Series
  • status: 返回client的请求的Http Status
  • httpStatusCode: 返回client的请求的httpStatusCode
  • httpMethod: ⽤于请求的HTTP⽅法
    另外通过 spring.cloud.gateway.metrics.tags.path.enabled (默认为false)来激活额外的指标:
  • path:请求的路径
    这些指标可以从 /actuator/metrics/spring.cloud.gateway.requests 获取,并且能够很容易的与Prometheus 集成创建Grafana dashboard。
    注意:要将pometheus启⽤,需要添加 micrometer-registry-prometheus 为项⽬依赖。
相关推荐
Rain的Java大神之路3 天前
如何快速上传10G文件
java·spring boot·redis·后端·mysql·spring cloud·面试
需要8263 天前
MySQL 索引 B+ 树与“查询为什么变慢了
java·spring boot·spring·spring cloud·tomcat
需要8263 天前
Arthas 一个命令排查线上问题
java·jvm·spring·spring cloud
Raas1003 天前
MAI Gateway(魔芋企业级AI网关)功能全解:AI网关支持流式输出吗?一文看懂AI网关能力矩阵
大数据·人工智能·gateway·mai gateway·企业级网关
苏渡苇4 天前
Spring Insight 里如何把 Span 画成瀑布时间线
后端·spring·spring cloud·springboot·监控·apm
叶总没有会4 天前
Nacos—注册中心
spring cloud·微服务
毅炼4 天前
不写多语言 SDK,怎么让 Python、Go、Node 服务接入注册中心?
java·后端·系统架构·gateway
苏渡苇5 天前
Spring Insight 里如何把 Span 收成一条链路
spring boot·spring·spring cloud·系统监控·apm
叶总没有会5 天前
微服务--分布式基础
java·spring·spring cloud·微服务
孙启超6 天前
【AI开发之Rust】第 7 课:错误处理 —— panic、Result 与 `?`
人工智能·分布式·后端·爬虫·spring cloud·架构·rust