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


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

    一、原理分析

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

    public interface GlobalFilter {
        Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain);
    }
    
    • 1
    • 2
    • 3

    再看一下GatewayFilter

    public interface GatewayFilter extends ShortcutConfigurable {
        Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain);
    }
    
    • 1
    • 2
    • 3

    可以看到GatewayFilter和GlobalFilter方法签名是一模一样的,那为啥又要整一个GlobalFilter出来?
    GatewayFilter的作用主要是,基于配置文件或者代码,就是routes那个配置,解析出配置,然后进行报文处理。这个Filter是跟某个route强行绑定的。
    GlobalFilter,是直接强制加载的,不属于某个指定的route。而这个filter需不需要处理,是通过在filter方法中来进行判断的。如果不需要自己处理,就直接丢给链条中下个filter。
    请求的处理逻辑,可以看以下代码
    FilteringWebHandler.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);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    代码解析:

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

    二、如何自定义一个GlobalFilter

    @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;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    三、内置的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

    spring:
      cloud:
        gateway:
          routes:
          - id: myRoute
            uri: lb://service
            predicates:
            - Path=/service/**
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    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

    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/**
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    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 为项⽬依赖。
  • 相关阅读:
    【Vue3 知识第七讲】reactive、shallowReactive、toRef、toRefs 等系列方法应用与对比
    Nginx进阶 配置-Nginx auth_basic 身份认证
    MFC自定义消息的实现方法----(线程向主对话框发送消息)、MFC不能用UpdateData的解决方法
    B2B还是F2B2C,谁是品牌商的未来?
    玩转亚马逊 AWS IoT(3): SpringBoot 2.7 集成 AWS IoT 服务
    spring-boot入门之如何利用idea创建一个spring-boot项目
    java 字符串练习(罗马数字的转换)
    数据结构:红黑树的插入实现(C++)
    Node.js 入门教程 26 npm 依赖与开发依赖 & 27 Node.js 包运行器 npx
    2019 CSP J2入门组 CSP-S2提高组 第2轮 视频与题解
  • 原文地址:https://blog.csdn.net/suyuaidan/article/details/132625746