参考:https://cloud.spring.io/spring-cloud-static/Greenwich.SR2/single/spring-cloud.html#_global_filters

全局过滤器 作用
Combined Global Filter and GatewayFilter Ordering 对过滤器执行顺序进行排序
Forward Routing Filter 用于本地forward,也就是将请求在Gateway服务内进行转发,而不是转发到下游服务
LoadBalancerClient Filter 整合Ribbon实现负载均衡
Netty Routing Filter 使用Netty的 HttpClient 转发http、https请求
Netty Write Response Filter 将代理响应写回网关的客户端侧
RouteToRequestUrl Filter 将从request里获取的原始url转换成Gateway进行请求转发时所使用的url
Websocket Routing Filter 使用Spring Web Socket将转发 Websocket 请求
Gateway Metrics Filter 整合监控相关,提供监控指标
Marking An Exchange As Routed 防止重复的路由转发

Combined Global Filter and GatewayFilter Ordering

当Gateway接收到请求时,Filtering Web Handler 处理器会将所有的 GlobalFilter 实例以及所有路由上所配置的 GatewayFilter 实例添加到一条过滤器链中。该过滤器链里的所有过滤器都会按照 org.springframework.core.Ordered 注解所指定的数字大小进行排序。

Spring Cloud Gateway区分了过滤器逻辑执行的 ”pre” 和 ”post” 阶段,所以优先级高的过滤器将会在 “pre” 阶段最先执行,优先级最低的过滤器则在 “post” 阶段最后执行。

  • 数字越小越靠前执行

示例代码:

  1. @Bean
  2. @Order(-1)
  3. public GlobalFilter a() {
  4. return (exchange, chain) -> {
  5. log.info("first pre filter");
  6. return chain.filter(exchange).then(Mono.fromRunnable(() -> {
  7. log.info("third post filter");
  8. }));
  9. };
  10. }
  11. @Bean
  12. @Order(0)
  13. public GlobalFilter b() {
  14. return (exchange, chain) -> {
  15. log.info("second pre filter");
  16. return chain.filter(exchange).then(Mono.fromRunnable(() -> {
  17. log.info("second post filter");
  18. }));
  19. };
  20. }
  21. @Bean
  22. @Order(1)
  23. public GlobalFilter c() {
  24. return (exchange, chain) -> {
  25. log.info("third pre filter");
  26. return chain.filter(exchange).then(Mono.fromRunnable(() -> {
  27. log.info("first post filter");
  28. }));
  29. };
  30. }

返回结果:

  1. first pre filter
  2. second pre filter
  3. third pre filter
  4. first post filter
  5. second post filter
  6. third post filter

Forward Routing Filter

当请求进来时,ForwardRoutingFilter 会查看一个URL,该URL为 exchange 属性 ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR 的值,如果该 url 的 scheme 是 forward(例如:forward://localendpoint),那么该Filter会使用Spirngd的DispatcherHandler 来处理这个请求。该请求的URL路径部分,会被forward URL中的路径覆盖掉。而未修改过的原始URL,会被追加到 ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR 属性中。

PS:所谓 url scheme 简单来说就是 url 中的协议部分,例如http、https、ws等。自定义的 scheme 通常用于标识该url的行为,例如app开发中通常使用url scheme来跳转页面

LoadBalancerClient Filter

这个Filter是用来整合Ribbon的,其核心就是解析 scheme 为lb的 url,以此获取微服务的名称,然后再通过Ribbon获取实际的调用地址。

当请求进来时,LoadBalancerClientFilter 会查看一个URL,该URL为 exchange 的属性 ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR 的值,如果该 url 的 scheme 是 lb,(例如:lb://myservice ),那么该Filter会使用Spring Cloud的 LoadBalancerClient 来将 myservice 解析成实际的host 和 port ,并替换掉原本 ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR 属性的值。而原始 url 会追加到 ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR 属性中。该过滤器还会查看 ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR 属性,如果发现该属性的值是 lb ,也会执行相同逻辑。

示例配置:

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

默认情况下,如果无法通过 LoadBalancer 找到指定服务的实例,那么会返回503(如上配置示例, 若 LoadBalancer 找不到名为 service 的实例时,就会返回503);可使用配置: spring.cloud.gateway.loadbalancer.use404=true ,让其返回404。

LoadBalancer 返回的 ServiceInstanceisSecure 的值,会覆盖请求的scheme。举个例子,如果请求打到Gateway上使用的是 HTTPS ,但 ServiceInstanceisSecure 是false,那么下游微服务接收到的则是HTTP请求,反之亦然。另外,如果该路由指定了 GATEWAY_SCHEME_PREFIX_ATTR 属性,那么前缀将会被剥离,并且路由URL中的scheme会覆盖 ServiceInstance 的配置。

Netty Routing Filter

当请求进来时,NettyRoutingFilter 会查看一个URL,该URL是 exchange 的属性 ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR 的值,如果该 url 的 scheme 是 httphttps ,那么该Filter会使用 Netty 的 HttpClient 向下游的服务发送代理请求。获得的响应将放在 exchange 的 ServerWebExchangeUtils.CLIENT_RESPONSE_ATTR 属性中,以便在后面的 Filter 里使用。(有一个实验性的过滤器: WebClientHttpRoutingFilter 可实现相同功能,但无需Netty)

Netty Write Response Filter

NettyWriteResponseFilter 用于将代理响应写回网关的客户端侧,所以该过滤器会在所有其他过滤器执行完成后才执行,并且执行的条件是 exchange 中 ServerWebExchangeUtils.CLIENT_RESPONSE_CONN_ATTR 属性的值不为空,该值为 Netty 的 Connection 实例。(有一个实验性的过滤器: WebClientWriteResponseFilter 可实现相同功能,但无需Netty)

RouteToRequestUrl Filter

这个过滤器用于将从request里获取的原始url转换成Gateway进行请求转发时所使用的url。当请求进来时,RouteToRequestUrlFilter 会从 exchange 中获取 ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR 属性的值,该值是一个 Route 对象。若该对象不为空的话,RouteToRequestUrlFilter 会基于请求 URL 及 Route 对象里的 URL 来创建一个新的 URL。新 URL 会被放到 exchange 的 ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR 属性中。

如果 URL 具有 scheme 前缀,例如 lb:ws://serviceid ,该 lb scheme将从URL中剥离,并放到 ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR 中,方便后面的过滤器使用。

Websocket Routing Filter

该过滤器的作用与 NettyRoutingFilter 类似。当请求进来时,WebsocketRoutingFilter 会查看一个URL,该URL是 exchange 中 ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR 属性的值,如果该 url 的 scheme 是 ws 或者 wss,那么该Filter会使用 Spring Web Socket 将 Websocket 请求转发到下游。

另外,如果 Websocket 请求需要负载均衡的话,可为URL添加 lb 前缀以实现负载均衡,例如 lb:ws://serviceid

示例配置:

  1. spring:
  2. cloud:
  3. gateway:
  4. routes:
  5. # SockJS route
  6. - id: websocket_sockjs_route
  7. uri: http://localhost:3001
  8. predicates:
  9. - Path=/websocket/info/**
  10. # Normwal Websocket route
  11. - id: websocket_route
  12. uri: ws://localhost:3001
  13. predicates:
  14. - Path=/websocket/**

Gateway Metrics Filter

想要启用Gateway Metrics Filter,需在项目中添加 spring-boot-starter-actuator 依赖,然后在配置文件中配置 spring.cloud.gateway.metrics.enabled 的值为true。该过滤器会添加名为 gateway.requests 的时序度量(timer metric),其中包含以下标记:

  • routeId:路由ID
  • routeUri:API将路由到的URI
  • outcome:由 HttpStatus.Series 分类
  • status:返回给客户端的Http Status
  • httpStatusCode:返回给客户端的请求的Http Status
  • httpMethod:请求所使用的Http方法

    这些指标暴露在 /actuator/metrics/gateway.requests 端点中,并且可以轻松与 Prometheus 整合,从而创建一个 Grafana dashboard。

PS:Prometheus是一款监控工具,Grafana是一款监控可视化工具;Spring Boot Actuator可与这两款工具进行整合。

Marking An Exchange As Routed

当一个请求走完整条过滤器链后,负责转发请求到下游的那个过滤器会在 exchange 中添加一个 gatewayAlreadyRouted 属性,从而将 exchange 标记为 routed(已路由)。一旦请求被标记为 routed ,其他路由过滤器将不会再次路由该请求,而是直接跳过。

了解了以上所有内置的全局过滤器后,我们知道不同协议的请求会由不同的过滤器转发到下游。所以负责添加这个gatewayAlreadyRouted 属性的过滤器就是最终负责转发请求的过滤器:

  • http、https请求会由NettyRoutingFilterWebClientHttpRoutingFilter添加这个属性
  • forward请求会由ForwardRoutingFilter添加这个属性
  • websocket请求会由WebsocketRoutingFilter添加这个属性

    这些过滤器调用了以下方法将 exchange 标记为 routed ,或检查 exchange 是否是 routed
  • ServerWebExchangeUtils.isAlreadyRouted:检查exchange是否为routed状态
  • ServerWebExchangeUtils.setAlreadyRouted:将exchange设置为routed状态

    简单来说,就是Gateway通过 gatewayAlreadyRouted 属性表示这个请求已经转发过了,而无需其他过滤器重复路由,从而防止重复的路由转发。

这些全局过滤器都有对应的配置类,感兴趣的话可以查看相关源码:

  • org.springframework.cloud.gateway.config.GatewayAutoConfiguration
  • org.springframework.cloud.gateway.config.GatewayMetricsAutoConfiguration
  • org.springframework.cloud.gateway.config.GatewayLoadBalancerClientAutoConfiguration

Spring Cloud Alibaba学习笔记(20) - Spring Cloud Gateway 内置的全局过滤器的更多相关文章

  1. Spring 源码学习笔记10——Spring AOP

    Spring 源码学习笔记10--Spring AOP 参考书籍<Spring技术内幕>Spring AOP的实现章节 书有点老,但是里面一些概念还是总结比较到位 源码基于Spring-a ...

  2. Spring 源码学习笔记11——Spring事务

    Spring 源码学习笔记11--Spring事务 Spring事务是基于Spring Aop的扩展 AOP的知识参见<Spring 源码学习笔记10--Spring AOP> 图片参考了 ...

  3. Flutter学习笔记(36)--常用内置动画

    如需转载,请注明出处:Flutter学习笔记(36)--常用内置动画 Flutter给我们提供了很多而且很好用的内置动画,这些动画仅仅需要简单的几行代码就可以实现一些不错的效果,Flutter的动画分 ...

  4. Spring Cloud Alibaba学习笔记(1) - 整合Spring Cloud Alibaba

    Spring Cloud Alibaba从孵化器版本毕业:https://github.com/alibaba/spring-cloud-alibaba,记录一下自己学习Spring Cloud Al ...

  5. Spring Cloud Alibaba学习笔记(21) - Spring Cloud Gateway 自定义全局过滤器

    在前文中,我们介绍了Spring Cloud Gateway内置了一系列的全局过滤器,本文介绍如何自定义全局过滤器. 自定义全局过滤需要实现GlobalFilter 接口,该接口和 GatewayFi ...

  6. Spring Cloud Alibaba学习笔记(19) - Spring Cloud Gateway 自定义过滤器工厂

    在前文中,我们介绍了Spring Cloud Gateway内置了一系列的内置过滤器工厂,若Spring Cloud Gateway内置的过滤器工厂无法满足我们的业务需求,那么此时就需要自定义自己的过 ...

  7. Spring Cloud Alibaba学习笔记(17) - Spring Cloud Gateway 自定义路由谓词工厂

    在前文中,我们介绍了Spring Cloud Gateway内置了一系列的路由谓词工厂,但是如果这些内置的路由谓词工厂不能满足业务需求的话,我们可以自定义路由谓词工厂来实现特定的需求. 例如有某个服务 ...

  8. Spring Cloud Alibaba学习笔记(16) - Spring Cloud Gateway 内置的路由谓词工厂

    Spring Cloud Gateway路由配置的两种形式 Spring Cloud Gateway的路由配置有两种形式,分别是路由到指定的URL以及路由到指定的微服务,在上文博客的示例中我们就已经使 ...

  9. Spring Cloud Alibaba学习笔记(15) - 整合Spring Cloud Gateway

    Spring Cloud Gateway 概述 Spring Cloud Gateway 是 Spring Cloud 的一个全新项目,该项目是基于Netty.Reactor以及WEbFlux构建,它 ...

随机推荐

  1. nuxt如何处理用户登录状态持久化:nuxtServerInit 页面渲染前的store处理

    vue-cli项目中,我们可以用vuex-persistedstate,它可以使vuex的状态持久化,页面刷新都不会丢失,原理当然是localStorage啦!当然也可以使用vue-cookies进行 ...

  2. GUI引发的一场脑部大战|wine、wsl、mono、gtk、qt

    没写完不想写了,先发布吧,这就是一个引子. 在春天种下一颗种子---- GUI引发的一场脑部大战|wine.wsl.mono.gtk.qt 思路开拓了,方法一下子就来了 wine可以运行大部分Wind ...

  3. ICEM-三棱锥的一种画法

    原视频下载地址:https://pan.baidu.com/s/1c4BAqy 密码: nqb4

  4. 安装docker (centos7.6)

    Docker 更新yum包 sudo yum update 卸载旧版本sudo yum remove docker docker-common docker-selinux docker-engine ...

  5. Linux下查看目录文件数和文件大小

    一.查看当前目录下文件个数 在linux下查看目录下有多少文件可以用:ls -l  命令查看,ls -lR 递归查看所有目录, 如果文件很多,则用wc命令 和 grep 命令进行过滤. wc命令显示输 ...

  6. 文件分片 浏览器文件大小限制 自定义请求头 在一个资源的加载进度停止之后被触发 arrayBuffer 异步 二进制数据缓存区

    js 整数限制 浏览器文件大小限制 https://w3c.github.io/FileAPI/#dom-blob-arraybuffer https://developer.mozilla.org/ ...

  7. Android : Camera HAL3的参数传递(CameraMetadata)

    一.camera_metadata简介 Camera API2/HAL3架构下使用了全新的CameraMetadata结构取代了之前的SetParameter/Paramters等操作,实现了Java ...

  8. 【转】HTML meta标签总结与属性使用介绍

    HTML meta标签总结与属性使用介绍 转载处写的已经超级好了,强烈推荐. 转自:https://segmentfault.com/a/1190000004279791 本人就不再赘述.拿来主义!供 ...

  9. Python3基础 list(dict) 使用 * 扩充时,出现字典元素重复问题

             Python : 3.7.3          OS : Ubuntu 18.04.2 LTS         IDE : pycharm-community-2019.1.3    ...

  10. Python3基础 函数 函数名赋值操作

             Python : 3.7.3          OS : Ubuntu 18.04.2 LTS         IDE : pycharm-community-2019.1.3    ...