SpringCloudGateway网关中各个过滤器的作用与介绍(附debug图片)

标签: springcloudgateway 网关 过滤器 | 发表时间:2023-10-03 16:04 | 作者:ZhangBlossom
出处:https://juejin.cn/backend

在我搭建的微服务项目中,网关是非常重要的一环,起到了请求过滤和拦截的。 我最近需要在网关实现URL请求参数加密以及数字签名检验请求参数是否被篡改等功能,所以最近着手开始研究起了网关。 首先最重要的就是先配置一个自己的过滤器,来完成验证。 然后就在设计的过程中遇到了一些问题,比如请求转发,请求request修改失败等问题。 所以学习一下源码,了解过滤器链就变得比较重要了。 这篇文章主要记录的是我对Gateway网关中比较重要的几个过滤器的作用的理解。 我的springcloudgateway的版本是3.1.4,还算可以,如下是filter包下面的过滤器。 在这里插入图片描述 下图是我的gateway的配置,以及我自定义的几个全局过滤器。 在这里插入图片描述

RemoveCachedBodyFilter

RemoveCachedBodyFilter是一个过滤器,用于在Spring Cloud Gateway中移除缓存的请求体。它的主要作用是清除在网关层缓存的请求体数据,以释放资源并避免对后续处理器的影响。

在Spring Cloud Gateway中,请求体是通过 CachedBodyHttpServletRequest对象进行缓存的。这个缓存的请求体可以在多个过滤器和处理器中被访问和读取。但在某些情况下,特别是在某个过滤器或处理器已经读取了请求体后,后续的处理器可能不再需要访问请求体,或者需要访问的请求体已经被处理完毕,这时就可以使用 RemoveCachedBodyFilter来移除缓存的请求体。

通过在过滤器链中添加 RemoveCachedBodyFilter,它会在请求被处理完毕后执行,将缓存的请求体从 CachedBodyHttpServletRequest对象中移除,以释放资源。这样可以避免请求体数据被无谓地传递到后续的处理器,提高性能和资源利用率。

需要注意的是, RemoveCachedBodyFilter通常需要在读取请求体的过滤器或处理器之后添加,以确保在处理完请求体后再进行清除操作。这样可以保证后续的处理器不会再访问到已经处理完毕的请求体数据,避免不必要的资源消耗。

AdaptCachedBodyGlobalFilter

AdaptCachedBodyGlobalFilter是一个全局过滤器,用于在请求到达网关时对请求进行处理。它的作用是将请求体缓存到网关中,以便在后续的请求中重复使用。这个过滤器通常用于优化跨集群的服务通信。

当使用微服务架构时,服务之间的通信可能需要经过网关进行路由和转发。在某些情况下,多个服务可能需要对同一个请求体进行处理,但由于HTTP请求的特性,请求体在传递过程中只能被读取一次。为了解决这个问题,AdaptCachedBodyGlobalFilter通过缓存请求体的方式,使得多个服务可以在后续的请求中重复使用该请求体。

通过缓存请求体,AdaptCachedBodyGlobalFilter可以提高服务之间的通信效率,减少不必要的数据传输和处理。它可以避免在每个服务中都重新读取请求体,从而节省了网络带宽和服务资源。

需要注意的是,AdaptCachedBodyGlobalFilter只能用于幂等的请求,因为对于非幂等的请求,重复使用缓存的请求体可能会导致数据不一致或产生意外的副作用。

AdaptCachedBodyGlobalFilter的作用是在网关层对请求体进行缓存,以提高跨集群服务通信的效率。

那么他是如何缓存的呢? 我总结成如下步骤: AdaptCachedBodyGlobalFilter通过以下步骤来缓存请求体:

当请求到达网关时,AdaptCachedBodyGlobalFilter会拦截该请求。

首先,它会检查请求的方法(HTTP verb)是否是幂等的,例如GET、HEAD、OPTIONS等。如果请求方法不是幂等的,过滤器将不会缓存请求体,而是继续将请求传递给下一个处理程序。

如果请求方法是幂等的,AdaptCachedBodyGlobalFilter会读取请求的内容(请求体),并将其缓存到网关的内存中。通常,缓存会使用一种合适的数据结构(例如字典或哈希表)来存储请求体。

缓存的请求体将与请求的唯一标识(例如请求的URL或请求头中的某个字段)相关联,以便在后续的请求中可以根据标识进行查找和重用。

当后续的请求到达网关时,AdaptCachedBodyGlobalFilter会检查请求的唯一标识,并尝试从缓存中获取相应的请求体。

如果找到了缓存的请求体,过滤器会将其重新注入到当前请求中,以便后续的处理程序可以使用该请求体进行处理。

通过以上步骤,AdaptCachedBodyGlobalFilter实现了对请求体的缓存和重用,提高了跨集群服务通信的效率。这样,多个服务可以在后续的请求中共享和重复使用同一个请求体,避免了重复的数据传输和处理。 具体的实现方法可以查看对应源码 在这里插入图片描述

NettyWriteResponseFilter

NettyWriteResponseFilter是一个过滤器,通常用于在网关层对响应进行处理和修改。它的主要作用是在响应发送到客户端之前,对响应进行一些额外的操作。

具体来说,NettyWriteResponseFilter的功能包括:

修改响应头信息:可以通过该过滤器修改响应的头部信息,例如添加、删除或修改特定的响应头字段。

响应内容转换:可以对响应的内容进行转换,例如将响应体从一种格式转换为另一种格式,例如JSON到XML的转换。

响应内容加密或解密:如果需要对响应进行加密或解密,可以使用该过滤器来执行相应的操作。

响应内容压缩:可以使用该过滤器对响应的内容进行压缩,以减小传输的数据量,提高网络传输效率。

响应内容缓存:在某些场景下,可以使用该过滤器对响应进行缓存,以提高响应速度和减轻后端服务的压力。

NettyWriteResponseFilter通常作为网关中的一个全局过滤器或者特定路由的过滤器链中的一个过滤器来使用。它可以对响应进行灵活的处理和修改,以满足特定的需求和业务逻辑。

ForwardPathFilter

如下是我的请求走到这一个过滤器的时候的情况,可以发现在这里它已经决定好了我当前的这个路径是需要路由到的一个位置。 在这里插入图片描述

ForwardPathFilter 是 Spring Cloud Gateway 中的一个过滤器,其主要作用是在请求转发(Forward)时,处理请求路径的修改和重写。它通常用于将请求从一个路径转发到另一个路径,并且可以在此过程中对请求路径进行修改。

具体作用和用例包括:

路径重写:可以将请求的路径重写为另一个路径,用于实现请求路径的重定向或路由。

路径添加:可以在现有路径的基础上添加额外的路径段,实现更复杂的路由逻辑。

路径删除:可以删除请求路径中的某些部分,以实现路径的简化。

路径替换:可以使用正则表达式等方式,将请求路径中的某些部分替换为其他内容。

举个例子,假设我现在一个网关路由,将 /v1/product 的请求转发到后端服务的 /products 路径上。我就可以使用 ForwardPathFilter 来实现这个转发,并且将请求路径中的 /v1 部分重写为空,从而实现路径的修改。

这个过滤器在网关路由的配置中,可以通过配置 predicates 和 filters 来实现不同的路径转发和修改需求。 如果想要实现我上面说的重置路由规则,你就直接继承这个类并且重写方法,然后设定为Spring的一个bean即可。

  import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
/**
* @author 张锦标
*/
@Component
public class CustomForwardPathFilter extends ForwardPathFilter {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 在这里实现您的自定义逻辑
        // 可以修改请求的路径或执行其他操作
        // 调用父类的方法来执行默认的ForwardPathFilter行为
        return super.filter(exchange, chain);
    }
}

RouteToRequestUrlFilter

RouteToRequestUrlFilter是Spring Cloud Gateway的一个过滤器,其主要作用是根据目标服务的URI来构建新的请求URI。这个过滤器通常在路由过程中使用,用于将客户端请求的URI映射到目标服务的URI,从而实现请求的转发。

具体来说,RouteToRequestUrlFilter的主要工作包括:

解析路由定义中的目标URI:它会从路由配置中获取目标服务的URI,通常是通过uri属性指定的。

构建新的请求URI:使用目标服务的URI和原始请求的URI来构建新的请求URI。这个新的URI将被用于将请求转发到目标服务。

更新请求的URI属性:将构建好的新URI应用到请求对象中,以确保后续的处理步骤使用正确的URI来路由请求。

示例使用:

假设您有一个Spring Cloud Gateway路由定义如下:

  routes:
  - id: my-route
    uri: http://example.com
    predicates:
      - Path=/my-service/**

当客户端发送一个请求到网关,如 http://gateway-server/my-service/resource,RouteToRequestUrlFilter将会解析路由配置中的uri属性(http://example.com),然后构建新的请求URI为http://example.com/resource。接下来,这个新的URI将被用于将请求转发到http://example.com上的/resource路径。

RouteToRequestUrlFilter是一个关键的过滤器,用于将客户端请求映射到目标服务的URI,从而实现路由和请求转发。

最后一步实现的请求路径的修改,就是在这个类中执行的,可以看到这里的两行代码

  URI mergedUrl = UriComponentsBuilder.fromUri(uri).scheme(routeUri.getScheme()).host(routeUri.getHost()).port(routeUri.getPort()).build(encoded).toUri();
//这一行代码可以修改request请求要请求的路径
exchange.getAttributes().put(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR, mergedUrl);

在这里插入图片描述 我之前试图在我自己的全局过滤器设定新的请求路径,结果每次都没生效,现在我终于知道原因了哈哈哈哈。所以说看源码还是有用。

WebSocketRoutingFilter

WebSocketRoutingFilter 是 Spring Cloud Gateway 中的一个过滤器,它用于处理 WebSocket 协议的请求,将 WebSocket 请求路由到目标 WebSocket 服务器。

具体来说,WebSocketRoutingFilter 的主要功能包括:

检测请求是否为 WebSocket 请求:它会检查客户端发来的请求是否包含 WebSocket 协议相关的标识,如 Upgrade 头部中是否包含 "websocket"。

构建 WebSocket 目标服务的 URI:如果请求被识别为 WebSocket 请求,过滤器将会根据路由配置中的目标 URI(通常是 WebSocket 服务器的地址)构建 WebSocket 目标服务的 URI。

路由 WebSocket 请求:过滤器将 WebSocket 请求路由到目标 WebSocket 服务器,以建立 WebSocket 连接。

连接转发:一旦 WebSocket 连接建立成功,过滤器会将客户端和目标 WebSocket 服务器之间的数据流量进行转发,使客户端能够与 WebSocket 服务器进行双向通信。

示例使用:

假设有一个 Spring Cloud Gateway 路由定义,用于将 WebSocket 请求转发到目标 WebSocket 服务器:

  routes:
  - id: websocket-route
    uri: ws://websocket-server
    predicates:
      - Path=/ws/**

NettyRoutingFilter

NettyRoutingFilter 是 Spring Cloud Gateway 中的一个过滤器,它负责将请求路由到目标服务并处理与目标服务之间的通信。这个过滤器是基于 Netty 框架实现的,用于处理非阻塞的异步请求和响应。

具体来说,NettyRoutingFilter 的主要作用包括:

负责将请求路由到目标服务:根据路由规则和请求的 URI,它决定了请求应该被路由到哪个目标服务。这通常涉及到根据请求的路径、主机名等信息来匹配路由规则,然后将请求发送给目标服务。

处理异步和非阻塞的请求:Spring Cloud Gateway 基于 Netty 提供了非阻塞的异步请求处理能力,允许处理大量并发请求而不会阻塞线程。NettyRoutingFilter 利用 Netty 的异步处理机制来实现这一点,从而提高了网关的性能和吞吐量。

处理请求和响应的转发:一旦确定了目标服务,过滤器会负责将请求和响应转发到目标服务,同时进行请求和响应的转换。这包括将请求头、请求体、响应头、响应体等内容从网关传递给目标服务,并从目标服务接收响应并返回给客户端。

处理请求失败和错误情况:如果请求无法成功路由到目标服务或者目标服务返回错误响应,NettyRoutingFilter 可以负责处理这些情况,并根据配置的策略来处理请求失败或错误的情况。

总之,NettyRoutingFilter 是 Spring Cloud Gateway 中关键的过滤器之一,它实现了请求的路由和异步非阻塞的请求处理,允许网关处理大量并发请求并将它们路由到目标服务。这有助于提高网关的性能和可扩展性。 在这一个过滤器中,会对你的请求头等信息进行一些操作 在这里插入图片描述

ForwardRoutingFilter

来到最后一个过滤器,最最最关键的一个过滤器,也就是我们请求转发过滤器。 ForwardRoutingFilter 是 Spring Cloud Gateway 中的一个过滤器(filter),用于实现请求的转发。Spring Cloud Gateway 是一个基于 Spring Framework 和 Spring Boot 的微服务网关,它提供了一种灵活而强大的方式来管理和路由微服务应用程序的请求流量。

ForwardRoutingFilter 的主要作用是将请求转发到指定的目标地址,通常是另一个微服务或后端服务。这个过滤器通常用于实现反向代理和请求的转发,将来自客户端的请求重新定向到后端服务,然后将后端服务的响应返回给客户端。

在 Spring Cloud Gateway 中,你可以通过配置路由规则来定义哪些请求应该由 ForwardRoutingFilter 这个过滤器处理,并指定转发的目标地址。

  spring:
  cloud:
    gateway:
      routes:
        - id: forward_route
          uri: http://backend-service:8080  # 后端服务的地址
          predicates:
            - Path=/api/**  # 匹配以 /api/ 开头的请求
          filters:
            - ForwardRoutingFilter   # 使用 ForwardRoutingFilter 进行请求转发

在这个示例中,路由规则指定了将以 "/api/" 开头的请求转发到后端服务的地址 http://backend-service:8080。ForwardRoutingFilter 将负责将这些请求转发到指定的地址,并将响应返回给客户端。

总之,ForwardRoutingFilter 是 Spring Cloud Gateway 中用于请求转发的关键过滤器,它允许你配置路由规则来定制请求的转发行为,从而实现反向代理和路由功能。

DispatcherHandler 是什么?

DispatcherHandler 是 Spring Framework 中用于处理 Web 请求的核心组件之一。它的主要作用是根据请求的 URL 路径将请求分发给不同的处理器(Handler),并协调执行请求处理的过程。DispatcherHandler 的具体职责包括以下几个方面:

URL 路径匹配:DispatcherHandler 根据请求的 URL 路径来确定应该由哪个处理器来处理请求。它会根据配置的请求映射规则(如@Controller 注解、@RequestMapping 注解等)将请求路由到相应的 Controller 方法。

处理器适配:一旦确定了请求应该由哪个 Controller 来处理,DispatcherHandler 会负责创建一个适配器(HandlerAdapter)来执行具体的 Controller 方法。不同类型的 Controller 可能有不同的适配器,例如处理常规请求的 Controller 适配器、处理异步请求的适配器等。

请求处理:DispatcherHandler 将请求和适配器传递给适配器,然后适配器负责调用相应的 Controller 方法来处理请求。Controller 方法执行后会生成一个模型(Model)对象,用于渲染视图。

视图解析:一旦请求处理完成,DispatcherHandler 还负责将模型传递给视图解析器(ViewResolver)来解析视图的名称,并生成实际的视图对象。这个视图对象通常是一个 HTML 模板、JSON 数据、XML 数据等,具体取决于请求和配置。

视图渲染:最后,DispatcherHandler 将生成的视图渲染到响应中,生成最终的响应内容,并将其返回给客户端浏览器或调用者。

⭐如何确定最后的路由路径?

我们知道,我们可以再Gateway网关中自定义过滤器,并且实现Ordered接口来对过滤器的执行顺序进行排序。如下图我实现了三个自定义的全局过滤器。 在这里插入图片描述

并且,当你实现全局过滤器接口的时候,你必须实现如下方法 public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) 其中exchange参数非常重要,他就是你的请求以及对你请求的响应。而chain就是上面的过滤器链条。 在这里插入图片描述

而我们的过滤器链的作用,其实就是对request和response这两个重要的类进行操作。 比如我可以使用exchange.mutate方法来对request和response进行修改。

  exchange = exchange.mutate().request(build -> {
            try {
                build.uri(
                        new URI("http://localhost:8080/v1/product?productId=1"))
                        .build();
            } catch (URISyntaxException e) {
                throw new RuntimeException(e);
            }
        }
).build();

如下是我修改request之前的请求体内容。 在这里插入图片描述

如下就是我修改URI之后的request请求体的内容。 在这里插入图片描述

在这里我们把这个reqeust给他修改有着重大意义,这意味着只要对加密后的数据进行解密后,去修改这个request中的内容,我们就能再一次成功的将我们的请求路由到我们指定的路径。 在这里插入图片描述

而之后,我们最终路由到的请求路径位置,保存在了DefaultServerWebExchange的attributes中。 在这里插入图片描述

最后只要进入到ForwardRoutingFilter 在这里插入图片描述

在这里请求完成了最终的处理,然后进行转发,发送到对应的处理类去处理。 这时候我们看提供远程服务调用的类的调用栈即可。 在这里插入图片描述

下文:如何根据过滤器链设计一个自己的数字签名?如何对URL上的参数进行加密解密来保证数据安全性?

敬请期待

相关 [springcloudgateway 网关 过滤器] 推荐:

SpringCloudGateway网关中各个过滤器的作用与介绍(附debug图片)

- - 掘金 后端
在我搭建的微服务项目中,网关是非常重要的一环,起到了请求过滤和拦截的. 我最近需要在网关实现URL请求参数加密以及数字签名检验请求参数是否被篡改等功能,所以最近着手开始研究起了网关. 首先最重要的就是先配置一个自己的过滤器,来完成验证. 然后就在设计的过程中遇到了一些问题,比如请求转发,请求request修改失败等问题.

JQuery内容过滤器

- - CSDN博客推荐文章
jQuery的选择器非常众多,下面介绍其中的一种,内容过滤器. 内容过滤器顾名思义就是根据内容进行选择的一种. 选择器,下面我们来举例一下这个内容过滤器的使用方法. 使用jQuery内容过滤器. $(function(){//显示包含给定文本的元素. $(function(){//显示所有不包含子元素或者文本的空元素.

JavaEE过滤器处理原理

- - ITeye博客
     大家都知道JavaEE中的Filter是用了责任链模式来实现的,请求值先到达Filter,根据Filter在web.xml的配置顺序一个个按顺序地处理,处理完以后,再按反顺序来处理响应信息,有点像是一个栈(先处理请求的Filter,后处理响应). 下面就山寨一下它的实现,来说明它的实现原理.

Hbase 布隆过滤器BloomFilter介绍

- - CSDN博客推荐文章
bloom filter的数据存在StoreFile的meta中,一旦写入无法更新,因为StoreFile是不可变的. Bloomfilter是一个列族(cf)级别的配置属性,如果你在表中设置了Bloomfilter,那么HBase会在生成StoreFile时包含一份bloomfilter结构的数据,称其为MetaBlock;MetaBlock与DataBlock(真实的KeyValue数据)一起由LRUBlockCache维护.

Wireshark 过滤器语法 - 粪球

- - 博客园_首页
 wireshark有两种过滤器:.  捕捉过滤器(CaptureFilters):用于决定将什么样的信息记录在捕捉结果中. 显示过滤器(DisplayFilters):用于在捕捉结果中进行详细查找. 捕捉过滤器 (此过滤器不需要比较运算符,查询关键字请全部小写). 捕捉过滤器是数据经过的第一层过滤器,它用于控制捕捉数据的数量,以避免产生过大的日志文件.

一个用于白名单服务的布隆过滤器(bloom filter)

- - CSDN博客架构设计推荐文章
      bloom filter这种数据结构用于判断一个元素是否在集合内,当然,这种功能也可以由HashMap来实现. bloom filter与HashMap的区别在于,HashMap会储存代表这个元素的key自身(如key为"IKnow7",那么HashMap将存储"IKnow7"这12个字节(java),其实还需要包括引用大小,但java中相同string只存一份),而bloom filter在底层只会使用几个bit来代表这个元素.

使用@WebFilter过滤器中设置例外URL的一种方式

- - 编程语言 - ITeye博客
        if (null!=excludedPages && excludedPages.length()!=0) { // 例外页面不为空   .         for (String page : excludedPageArray) {// 遍历例外url数组   .             // 判断当前URL是否与例外页面相同.

Spring Security 实战干货:图解Spring Security中的Servlet过滤器体系

- - SegmentFault 最新的文章
我在 Spring Security 实战干货:内置 Filter 全解析对 Spring Security的内置过滤器进行了罗列,但是 Spring Security真正的过滤器体系才是我们了解它是如何进行"认证"、“授权”、“防止利用漏洞”的关键. Servlet Filter体系. 这里我们以 Servlet Web为讨论目标, Reactive Web暂不讨论.

详谈布隆过滤器在亿级流量电商系统的应用

- - 掘金 架构
本文已参与「新人创作礼」活动,一起开启掘金创作之路. 布隆过滤器在实际中发挥着非常重要的作用,一呢可以防止网站被攻击,二呢可以提高系统的性能. 接下来我们通过实际案例进行讲解. 例如在电商平台,下面商品访问的地址为 https://item.jd.com/ 857.html,其中 857 是商品的 SKU.

API 网关 Kong

- - IT瘾-tuicool
所谓网关,主要作用就是连接两个不同网络的设备,而今天所讲的 API 网关是指承接和分发客户端所有请求的网关层. 最初是单体服务时,客户端发起的所有请求都可以直接请求到该服务,但随着产品用户越来越多,单体应用存在显而易见的单点问题,除此之外,当单体应用大小升至几个 G 时,持续发布将会非常缓慢,所以服务的拆分成为了必然趋势.