热门标签 | HotTags
当前位置:  开发笔记 > 运维 > 正文

详解SpringCloudGateway之过滤器GatewayFilter

这篇文章主要介绍了详解SpringCloudGateway之过滤器GatewayFilter,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

在Spring-Cloud-Gateway之请求处理流程文中我们了解最终网关是将请求交给过滤器链表进行处理,接下来我们阅读Spring-Cloud-Gateway的整个过滤器类结构以及主要功能

通过源码可以看到Spring-Cloud-Gateway的filter包中吉接口有如下三个,GatewayFilter,GlobalFilter,GatewayFilterChain,下来我依次阅读接口的主要实现功能。

GatewayFilterChain

类图


代码

/**
 * 网关过滤链表接口
 * 用于过滤器的链式调用
 * Contract to allow a {@link WebFilter} to delegate to the next in the chain.
 *
 * @author Rossen Stoyanchev
 * @since 5.0
 */
public interface GatewayFilterChain {

  /**
   * 链表启动调用入口方法
   * Delegate to the next {@code WebFilter} in the chain.
   * @param exchange the current server exchange
   * @return {@code Mono} to indicate when request handling is complete
   */
  Mono filter(ServerWebExchange exchange);

}
  /**
   * 网关过滤的链表,用于过滤器的链式调用
   * 过滤器链表接口的默认实现,
   * 包含2个构建函数:
   * 1.集合参数构建用于初始化吧构建链表
   * 2. index,parent参数用于构建当前执行过滤对应的下次执行的链表 
   */
  private static class DefaultGatewayFilterChain implements GatewayFilterChain {

    /**
     * 当前过滤执行过滤器在集合中索引
     */
    private final int index;
    /**
     * 过滤器集合
     */
    private final List filters;

    public DefaultGatewayFilterChain(List filters) {
      this.filters = filters;
      this.index = 0;
    }

    /**
     * 构建
     * @param parent 上一个执行过滤器对应的FilterChain
     * @param index 当前要执行过滤器的索引
     */
    private DefaultGatewayFilterChain(DefaultGatewayFilterChain parent, int index) {
      this.filters = parent.getFilters();
      this.index = index;
    }

    public List getFilters() {
      return filters;
    }

    /**
     * @param exchange the current server exchange
     * @return
     */
    @Override
    public Mono filter(ServerWebExchange exchange) {
      return Mono.defer(() -> {
        if (this.index 

过滤器的GatewayFilterChain 执行顺序

  1. 通过GatewayFilter集合构建顶层的GatewayFilterChain
  2. 调用顶层GatewayFilterChain,获取第一个Filter,并创建下一个Filter索引对应的GatewayFilterChain
  3. 调用filter的filter方法执行当前filter,并将下次要执行的filter对应GatewayFilterChain传入。

GatewayFilter

类图

/**
 * 网关路由过滤器,
 * Contract for interception-style, chained processing of Web requests that may
 * be used to implement cross-cutting, application-agnostic requirements such
 * as security, timeouts, and others. Specific to a Gateway
 *
 * Copied from WebFilter
 *
 * @author Rossen Stoyanchev
 * @since 5.0
 */
public interface GatewayFilter extends ShortcutConfigurable {

  String NAME_KEY = "name";
  String VALUE_KEY = "value";

  /**
   * 过滤器执行方法
   * Process the Web request and (optionally) delegate to the next
   * {@code WebFilter} through the given {@link GatewayFilterChain}.
   * @param exchange the current server exchange
   * @param chain provides a way to delegate to the next filter
   * @return {@code Mono} to indicate when request processing is complete
   */
  Mono filter(ServerWebExchange exchange, GatewayFilterChain chain);

}

网关过滤器接口,有且只有一个方法filter,执行当前过滤器,并在此方法中决定过滤器链表是否继续往下执行,接下来我们看下几个主要的功能实现类

OrderedGatewayFilter

/**
 * 排序的网关路由过滤器,用于包装真实的网关过滤器,已达到过滤器可排序
 * @author Spencer Gibb
 */
public class OrderedGatewayFilter implements GatewayFilter, Ordered {

  //目标过滤器
  private final GatewayFilter delegate;
  //排序字段
  private final int order;

  public OrderedGatewayFilter(GatewayFilter delegate, int order) {
    this.delegate = delegate;
    this.order = order;
  }

  @Override
  public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    return this.delegate.filter(exchange, chain);
  }
}  

OrderedGatewayFilter实现类主要目的是为了将目标过滤器包装成可排序的对象类型。是目标过滤器的包装类

GatewayFilterAdapter

  /**
   * 全局过滤器的包装类,将全局路由包装成统一的网关过滤器
   */
  private static class GatewayFilterAdapter implements GatewayFilter {

    /**
     * 全局过滤器
     */
    private final GlobalFilter delegate;

    public GatewayFilterAdapter(GlobalFilter delegate) {
      this.delegate = delegate;
    }

    @Override
    public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
      return this.delegate.filter(exchange, chain);
    }
  }

GatewayFilterAdapter实现类主要目的是为了将GlobalFilter过滤器包装成GatewayFilter类型的对应。是GlobalFilter过滤器的包装类

GlobalFilter

GlobalFilter 为请求业务以及路由的URI转换为真实业务服务的请求地址的核心过滤器,不需要配置,模式系统初始化时加载,并作用在每个路由上。

初始化加载,通过GatewayAutoConfiguration自动创建

GatewayAutoConfiguration 类

    /**
     * 全局过滤器,用户通过HttpClient转发请求
     * @param httpClient
     * @param headersFilters
     * @return
     */
    @Bean
    public NettyRoutingFilter routingFilter(HttpClient httpClient,
                        ObjectProvider> headersFilters) {
      return new NettyRoutingFilter(httpClient, headersFilters);
    }

    /**
     * 全局的过滤器,用户将HttpClient客户端转发请求的响应写入到原始的请求响应中
     * @param properties
     * @return
     */
    @Bean
    public NettyWriteResponseFilter nettyWriteResponseFilter(GatewayProperties properties) {
      return new NettyWriteResponseFilter(properties.getStreamingMediaTypes());
    }

GatewayLoadBalancerClientAutoConfiguration 类

  /**
   * 全局过滤器,用于在通过负载均衡客户端选择服务实例信息
   * @param client
   * @return
   */
  @Bean
  @ConditionalOnBean(LoadBalancerClient.class)
  public LoadBalancerClientFilter loadBalancerClientFilter(LoadBalancerClient client) {
    return new LoadBalancerClientFilter(client);
  }

GlobalFilter转换成GatewayFilter,并作用于每个路由上,在FilteringWebHandler实现

FilteringWebHandler类

  /**
   * 包装加载全局的过滤器,将全局过滤器包装成GatewayFilter
   * @param filters
   * @return
   */
  private static List loadFilters(List filters) {
    return filters.stream()
        .map(filter -> {
          //将所有的全局过滤器包装成网关过滤器
          GatewayFilterAdapter gatewayFilter = new GatewayFilterAdapter(filter);
          //判断全局过滤器是否实现了可排序接口
          if (filter instanceof Ordered) {
            int order = ((Ordered) filter).getOrder();
            //包装成可排序的网关过滤器
            return new OrderedGatewayFilter(gatewayFilter, order);
          }
          return gatewayFilter;
        }).collect(Collectors.toList());
  }
  @Override
  public Mono handle(ServerWebExchange exchange) {
    //获取请求上下文设置的路由实例
    Route route = exchange.getRequiredAttribute(GATEWAY_ROUTE_ATTR);
    //获取路由定义下的网关过滤器集合
    List gatewayFilters = route.getFilters();

    //组合全局的过滤器与路由配置的过滤器
    List combined = new ArrayList<>(this.globalFilters);
    //添加路由配置过滤器到集合尾部
    combined.addAll(gatewayFilters);
    //对过滤器进行排序
    //TODO: needed or cached&#63;
    AnnotationAwareOrderComparator.sort(combined);

    logger.debug("Sorted gatewayFilterFactories: "+ combined);
    //创建过滤器链表对其进行链式调用
    return new DefaultGatewayFilterChain(combined).filter(exchange);
  }

loadFilters方法是将全局路由使用GatewayFilterAdapter包装成GatewayFilter

handle方法

  • 获取当前请求使用的路由Route
  • 获取路由配置的过滤器集合route.getFilters()
  • 合并全过滤器与路由配置过滤器combined
  • 对过滤器排序AnnotationAwareOrderComparator.sort
  • 通过过滤器集合构建顶级链表DefaultGatewayFilterChain,并对其当前请求调用链表的filter方法。

==备注==:

Spring-Cloud-Gateway的过滤器接口分为两种:

  • GlobalFilter : 全局过滤器,不需要在配置文件中配置,作用在所有的路由上,最终通过GatewayFilterAdapter包装成GatewayFilterChain可识别的过滤器
  • GatewayFilter : 需要通过spring.cloud.routes.filters 配置在具体路由下,只作用在当前路由上或通过spring.cloud.default-filters配置在全局,作用在所有路由上

至此,网关过滤器的整个结构以及加载使用流程源码已经阅读完毕,下篇重点学习下路由配置的过滤器加载创建流程

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


推荐阅读
  • 第二章:Kafka基础入门与核心概念解析
    本章节主要介绍了Kafka的基本概念及其核心特性。Kafka是一种分布式消息发布和订阅系统,以其卓越的性能和高吞吐量而著称。最初,Kafka被设计用于LinkedIn的活动流和运营数据处理,旨在高效地管理和传输大规模的数据流。这些数据主要包括用户活动记录、系统日志和其他实时信息。通过深入解析Kafka的设计原理和应用场景,读者将能够更好地理解其在现代大数据架构中的重要地位。 ... [详细]
  • 本文首先介绍了BGP的基本概念和基础知识,详细解析了BGP的不同邻居类型及其作用。接着,文章对BGP的报文格式、状态机以及路由宣告原则进行了深入探讨,包括本地宣告、引入宣告和缺省路由的处理方法。通过这些内容,读者可以全面了解BGP路由协议的核心机制及其在实际网络中的应用。 ... [详细]
  • 负载均衡基础概念与技术解析
    随着互联网应用的不断扩展,用户流量激增,业务复杂度显著提升,单一服务器已难以应对日益增长的负载需求。负载均衡技术应运而生,通过将请求合理分配到多个服务器,有效提高系统的可用性和响应速度。本文将深入探讨负载均衡的基本概念和技术原理,分析其在现代互联网架构中的重要性及应用场景。 ... [详细]
  • 本文详细解析了神州数码DCRS5980交换机的基础配置流程和技术要点。首先,通过进入配置模式(`enable`),设置主机名(`hostname 5980`),并创建VLAN,逐步介绍了设备的初始设置步骤。此外,还涵盖了端口配置、IP地址分配及安全设置等关键环节,为用户提供了全面的配置指导。 ... [详细]
  • 2019年后蚂蚁集团与拼多多面试经验详述与深度剖析
    2019年后蚂蚁集团与拼多多面试经验详述与深度剖析 ... [详细]
  • 本文深入探讨了 Spring Cloud 微服务架构中 Gateway 组件的应用,详细介绍了其在实现高效请求路由与过滤方面的关键作用。文章首先从基本配置入手,逐步讲解了如何通过静态路由和动态路由实现灵活的服务访问控制。此外,还特别介绍了如何配置 Gateway 以自动从 Nacos 服务注册中心拉取服务列表,进一步提升系统的可维护性和扩展性。 ... [详细]
  • IIS 7及7.5版本中应用程序池的最佳配置策略与实践
    在IIS 7及7.5版本中,优化应用程序池的配置是提升Web站点性能的关键步骤。具体操作包括:首先定位到目标Web站点的应用程序池,然后通过“应用程序池”菜单找到对应的池,右键选择“高级设置”。在一般优化方案中,建议调整以下几个关键参数:1. **基本设置**: - **队列长度**:默认值为1000,可根据实际需求调整队列长度,以提高处理请求的能力。此外,还可以进一步优化其他参数,如处理器使用限制、回收策略等,以确保应用程序池的高效运行。这些优化措施有助于提升系统的稳定性和响应速度。 ... [详细]
  • ZeroMQ在云计算环境下的高效消息传递库第四章学习心得
    本章节深入探讨了ZeroMQ在云计算环境中的高效消息传递机制,涵盖客户端请求-响应模式、最近最少使用(LRU)队列、心跳检测、面向服务的队列、基于磁盘的离线队列以及主从备份服务等关键技术。此外,还介绍了无中间件的请求-响应架构,强调了这些技术在提升系统性能和可靠性方面的应用价值。个人理解方面,ZeroMQ通过这些机制有效解决了分布式系统中常见的通信延迟和数据一致性问题。 ... [详细]
  • 如何在主服务器响应变慢时,自动切换至备用服务器地址以确保服务连续性
    在主服务器响应速度下降时,如何通过编程实现自动切换至备用服务器地址,以确保服务的连续性和稳定性。本文将介绍一种基于PHP和MySQL的解决方案,通过监测主服务器的响应时间,当检测到延迟过高时,自动切换至备用服务器接口,从而保障系统的高可用性。 ... [详细]
  • 黄聪:MySQL主从复制配置,实现高效读写分离
    大型网站为应对高并发访问,不仅需要在前端实现分布式负载均衡,还需在数据业务和访问层采取有效措施。采用传统的数据结构已无法满足需求,通过配置MySQL主从复制,可实现高效的读写分离,显著提升系统性能和稳定性。 ... [详细]
  • 本文深入解析了 Golang 中的异步 API,并通过具体的应用实例展示了其强大功能。文章不仅探讨了 Golang 和 Erlang 在并行处理方面的核心理念,还详细介绍了如何利用通道(channel)和 goroutine 实现高效的并发编程。例如,通过 `ch := make(chan int)` 创建通道,并使用 `go func(ch chan int)` 启动 goroutine 来处理异步任务。此外,文章还提供了多个实际案例,帮助读者更好地理解和应用这些概念。 ... [详细]
  • Zuul过滤器:深入解析与应用优化
    在服务网关中实现过滤器,只需继承抽象类并实现其定义的四个关键方法,即可对请求进行拦截和处理。过滤器具有两大核心功能:一是路由功能,负责将外部请求转发至具体的微服务实例,实现外部访问的统一入口;二是过滤功能,用于对请求进行预处理和后处理,增强系统的安全性和性能。通过合理配置和优化过滤器,可以显著提升服务网关的整体效能。 ... [详细]
  • 程序员们欢呼雀跃:微软正式推出GitHub安卓版应用预览版,新增暗黑模式支持
    近日,GitHub正式发布了面向Android用户的移动应用预览版,这一消息让众多程序员兴奋不已。新版本不仅支持暗黑模式,还优化了用户体验,为开发者提供了更加便捷的代码管理和协作工具。此前,GitHub已为iOS用户推出了相应的移动应用,此次Android版的发布进一步扩大了其在移动开发领域的影响力。 ... [详细]
  • Nginx入门指南:从零开始掌握基础配置与优化技巧
    Nginx入门指南:从零开始掌握基础配置与优化技巧 ... [详细]
  • 前言: 网上搭建k8s的文章很多,但很多都无法按其说明在阿里云ecs服务器成功搭建,所以我就花了些时间基于自己成功搭建k8s的步骤写了个操作手册,希望对想搭建k8s环境的盆友有所帮 ... [详细]
author-avatar
啊健oo
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有