Spring Cloud Gateway 源码剖析之Filter Chain过滤器链

简介: Spring Cloud Gateway 源码剖析之Filter Chain过滤器链

一、前言

前几篇我们讲了 Gateway 相应的初始化、路由相关模型以及 Predicate 谓词详解,这一篇我们再来讲一下 Filter Chain 过滤器链,讲完这一篇,相信你对 Gateway 源码整体设计思想有个深刻的体会了,后续你想去抠细节也不是什么难事了。前几篇可以回顾下:

Spring Cloud Gateway 源码剖析之配置初始化

Spring Cloud Gateway 源码剖析之Route数据模型

Spring Cloud Gateway 源码剖析之Predicate谓词详解

回顾完了我们再来看一张 Spring Cloud Gateway 的整体流程图,相信一直看完这个系列的很快的就能知道上一篇我们讲到了 Predicate 断言这一块,如果 Handler Mapping 匹配成功则会通过 GatewayWebHandler 创建请求对应的 Route 对应的 Filter Chain 来进行处理请求。我们按照这个流程图来看的话,接下来要讲的是通过网关自定义的 WebHandler 来处理请求,这里就来讲一下最重要 FilteringWebHandler 过滤器链。

二、FilteringWebHandler

// org.springframework.cloud.gateway.handler.FilteringWebHandler
/**
 * 通过过滤器处理web请求的处理器
 */
public class FilteringWebHandler implements WebHandler {
    protected static final Log logger = LogFactory.getLog(FilteringWebHandler.class);
    /**
     * 全局过滤器
     */
    private final List<GatewayFilter> globalFilters;
    public FilteringWebHandler(List<GlobalFilter> globalFilters) {
        this.globalFilters = loadFilters(globalFilters);
    }
    /**
     * 组成过滤链
     * 包装加载全局的过滤器,将全局过滤器包装成GatewayFilter
     */
    private static List<GatewayFilter> loadFilters(List<GlobalFilter> filters) {
        return (List)filters.stream().map((filter) -> {
            FilteringWebHandler.GatewayFilterAdapter gatewayFilter = new FilteringWebHandler.GatewayFilterAdapter(filter);
            // 当 GlobalFilter 子类实现了 org.springframework.core.Ordered 接口,在委托一层 OrderedGatewayFilter 。
            // 这样 AnnotationAwareOrderComparator#sort(List) 方法好排序。
            if (filter instanceof Ordered) {
                int order = ((Ordered)filter).getOrder();
                return new OrderedGatewayFilter(gatewayFilter, order);
            } else {
                return gatewayFilter;
            }
        }).collect(Collectors.toList());
    }
    // 按照过滤链的顺序依次执行
    public Mono<Void> handle(ServerWebExchange exchange) {
        // 获取请求上下文设置的路由实例
        Route route = (Route)exchange.getRequiredAttribute(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR);
        // 获取路由定义下的网关过滤器集合
        List<GatewayFilter> gatewayFilters = route.getFilters();
        // 组合全局的过滤器与路由配置的过滤器
        List<GatewayFilter> combined = new ArrayList(this.globalFilters);
        // 添加路由配置过滤器到集合尾部
        combined.addAll(gatewayFilters);
        // 对过滤器进行排序
        AnnotationAwareOrderComparator.sort(combined);
        if (logger.isDebugEnabled()) {
            logger.debug("Sorted gatewayFilterFactories: " + combined);
        }
        // 创建过滤器链表对其进行链式调用
        return (new FilteringWebHandler.DefaultGatewayFilterChain(combined)).filter(exchange);
    }
    ...
}

FilteringWebHandler 的执行顺序:

  • 构建一个包含全局过滤器的集合(combined)
  • 获取上下文中的路由信息 GATEWAY_ROUTE_ATTR
  • 将路由里的过滤器添加到集合中(combined)
  • 对过滤器集合进行排序操作
  • 通过过滤器集合组装过滤器链表,并进行调用(DefaultGatewayFilterChain 与 Servlet 中的 FilterChain 的原理是一致的)
  • 通过过滤器来处理请求到具体业务服务

2.1 GatewayFilter 与 GlobalFilter 的关系

private final List<GatewayFilter> globalFilters;
public FilteringWebHandler(List<GlobalFilter> globalFilters) {
    this.globalFilters = loadFilters(globalFilters);
}

2.1.1 GatewayFilter 网关过滤器接口

public interface GatewayFilter extends ShortcutConfigurable {
    String NAME_KEY = "name";
    String VALUE_KEY = "value";
    Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain);
}

GatewayFilter 有三种类型的子类实现

  • OrderedGatewayFilter :有序的网关过滤器实现类。在 FilterChain 里,过滤器数组首先会按照 order 升序排序,按照顺序过滤请求。
public class OrderedGatewayFilter implements GatewayFilter, Ordered {
    // 委托的 GatewayFilter
    private final GatewayFilter delegate;
    // order代表顺序
    private final int order;
    public OrderedGatewayFilter(GatewayFilter delegate, int order) {
        this.delegate = delegate;
        this.order = order;
    }
    public GatewayFilter getDelegate() {
        return this.delegate;
    }
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        return this.delegate.filter(exchange, chain);
    }
    public int getOrder() {
        return this.order;
    }
    public String toString() {
        StringBuilder sb = new StringBuilder("OrderedGatewayFilter{");
        sb.append("delegate=").append(this.delegate);
        sb.append(", order=").append(this.order);
        sb.append('}');
        return sb.toString();
    }
}

   

  • GatewayFilterAdapter:网关过滤器适配器。在 GatewayFilterChain 使用 GatewayFilter 过滤请求,所以通过 GatewayFilterAdapter 将 GlobalFilter 适配成 GatewayFilter。
private static class GatewayFilterAdapter implements GatewayFilter {
    // 委托的 GlobalFilter
    private final GlobalFilter delegate;
    public GatewayFilterAdapter(GlobalFilter delegate) {
        this.delegate = delegate;
    }
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        return this.delegate.filter(exchange, chain);
    }
    public String toString() {
        StringBuilder sb = new StringBuilder("GatewayFilterAdapter{");
        sb.append("delegate=").append(this.delegate);
        sb.append('}');
        return sb.toString();
    }
}
  • ModifyResponseGatewayFilter:用于修改 Response
public class ModifyResponseGatewayFilter implements GatewayFilter, Ordered {
    private final ModifyResponseBodyGatewayFilterFactory.Config config;
    public ModifyResponseGatewayFilter(ModifyResponseBodyGatewayFilterFactory.Config config) {
        this.config = config;
    }
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpResponseDecorator responseDecorator = new ServerHttpResponseDecorator(exchange.getResponse()) {
            public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
                Class inClass = ModifyResponseGatewayFilter.this.config.getInClass();
                Class outClass = ModifyResponseGatewayFilter.this.config.getOutClass();
                String originalResponseContentType = (String)exchange.getAttribute("original_response_content_type");
                HttpHeaders httpHeaders = new HttpHeaders();
                httpHeaders.add("Content-Type", originalResponseContentType);
                ModifyResponseBodyGatewayFilterFactory.ResponseAdapter responseAdapter = ModifyResponseBodyGatewayFilterFactory.this.new ResponseAdapter(body, httpHeaders);
                DefaultClientResponse clientResponse = new DefaultClientResponse(responseAdapter, ExchangeStrategies.withDefaults());
                Mono modifiedBody = clientResponse.bodyToMono(inClass).flatMap((originalBody) -> {
                    return ModifyResponseGatewayFilter.this.config.rewriteFunction.apply(exchange, originalBody);
                });
                BodyInserter bodyInserter = BodyInserters.fromPublisher(modifiedBody, outClass);
                CachedBodyOutputMessage outputMessage = new CachedBodyOutputMessage(exchange, exchange.getResponse().getHeaders());
                return bodyInserter.insert(outputMessage, new BodyInserterContext()).then(Mono.defer(() -> {
                    Flux<DataBuffer> messageBody = outputMessage.getBody();
                    HttpHeaders headers = this.getDelegate().getHeaders();
                    if (!headers.containsKey("Transfer-Encoding")) {
                        messageBody = messageBody.doOnNext((data) -> {
                            headers.setContentLength((long)data.readableByteCount());
                        });
                    }
                    return this.getDelegate().writeWith(messageBody);
                }));
            }
            public Mono<Void> writeAndFlushWith(Publisher<? extends Publisher<? extends DataBuffer>> body) {
                return this.writeWith(Flux.from(body).flatMapSequential((p) -> {
                    return p;
                }));
            }
        };
        return chain.filter(exchange.mutate().response(responseDecorator).build());
    }
    public int getOrder() {
        return -2;
    }
}

2.1.2 GlobalFilter 全局过滤器接口,会作用到所有的Route上。

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

三、GatewayFilterFactory

在上一篇 Spring Cloud Gateway 源码剖析之Predicate谓词详解 中,已经详细介绍了 PredicateFactory 的各种子类实现。GatewayFilterFactory 也一样,这里就详细分析了哈。




欢迎大家关注我的公众号【老周聊架构】,Java后端主流技术栈的原理、源码分析、架构以及各种互联网高并发、高性能、高可用的解决方案。


喜欢的话,点赞、再看、分享三连。


相关文章
|
2月前
|
JSON Java API
利用Spring Cloud Gateway Predicate优化微服务路由策略
Spring Cloud Gateway 的路由配置中,`predicates`​(断言)用于定义哪些请求应该匹配特定的路由规则。 断言是Gateway在进行路由时,根据具体的请求信息如请求路径、请求方法、请求参数等进行匹配的规则。当一个请求的信息符合断言设置的条件时,Gateway就会将该请求路由到对应的服务上。
181 69
利用Spring Cloud Gateway Predicate优化微服务路由策略
|
1月前
|
监控 JavaScript 数据可视化
建筑施工一体化信息管理平台源码,支持微服务架构,采用Java、Spring Cloud、Vue等技术开发。
智慧工地云平台是专为建筑施工领域打造的一体化信息管理平台,利用大数据、云计算、物联网等技术,实现施工区域各系统数据汇总与可视化管理。平台涵盖人员、设备、物料、环境等关键因素的实时监控与数据分析,提供远程指挥、决策支持等功能,提升工作效率,促进产业信息化发展。系统由PC端、APP移动端及项目、监管、数据屏三大平台组成,支持微服务架构,采用Java、Spring Cloud、Vue等技术开发。
|
2月前
|
JavaScript Java Kotlin
深入 Spring Cloud Gateway 过滤器
Spring Cloud Gateway 是新一代微服务网关框架,支持多种过滤器实现。本文详解了 `GlobalFilter`、`GatewayFilter` 和 `AbstractGatewayFilterFactory` 三种过滤器的实现方式及其应用场景,帮助开发者高效利用这些工具进行网关开发。
355 1
|
2月前
|
消息中间件 监控 Java
如何将Spring Boot + RabbitMQ应用程序部署到Pivotal Cloud Foundry (PCF)
如何将Spring Boot + RabbitMQ应用程序部署到Pivotal Cloud Foundry (PCF)
47 6
|
2月前
|
Java 关系型数据库 MySQL
如何将Spring Boot + MySQL应用程序部署到Pivotal Cloud Foundry (PCF)
如何将Spring Boot + MySQL应用程序部署到Pivotal Cloud Foundry (PCF)
80 5
|
2月前
|
缓存 监控 Java
如何将Spring Boot应用程序部署到Pivotal Cloud Foundry (PCF)
如何将Spring Boot应用程序部署到Pivotal Cloud Foundry (PCF)
60 5
|
3月前
|
负载均衡 Java API
项目中用的网关Gateway及SpringCloud
Spring Cloud Gateway 是一个功能强大、灵活易用的API网关解决方案。通过配置路由、过滤器、熔断器和限流等功能,可以有效地管理和保护微服务。本文详细介绍了Spring Cloud Gateway的基本概念、配置方法和实际应用,希望能帮助开发者更好地理解和使用这一工具。通过合理使用Spring Cloud Gateway,可以显著提升微服务架构的健壮性和可维护性。
90 0
|
5月前
|
设计模式 Java 关系型数据库
【Java笔记+踩坑汇总】Java基础+JavaWeb+SSM+SpringBoot+SpringCloud+瑞吉外卖/谷粒商城/学成在线+设计模式+面试题汇总+性能调优/架构设计+源码解析
本文是“Java学习路线”专栏的导航文章,目标是为Java初学者和初中高级工程师提供一套完整的Java学习路线。
531 37
|
5月前
|
负载均衡 Java Nacos
SpringCloud基础2——Nacos配置、Feign、Gateway
nacos配置管理、Feign远程调用、Gateway服务网关
SpringCloud基础2——Nacos配置、Feign、Gateway
|
5月前
|
负载均衡 Java 网络架构
实现微服务网关:Zuul与Spring Cloud Gateway的比较分析
实现微服务网关:Zuul与Spring Cloud Gateway的比较分析
255 5