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月前
|
设计模式 Java 开发者
如何快速上手【Spring AOP】?从动态代理到源码剖析(下篇)
Spring AOP的实现本质上依赖于代理模式这一经典设计模式。代理模式通过引入代理对象作为目标对象的中间层,实现了对目标对象访问的控制与增强,其核心价值在于解耦核心业务逻辑与横切关注点。在框架设计中,这种模式广泛用于实现功能扩展(如远程调用、延迟加载)、行为拦截(如权限校验、异常处理)等场景,为系统提供了更高的灵活性和可维护性。
|
3月前
|
前端开发 Java API
Spring Cloud Gateway Server Web MVC报错“Unsupported transfer encoding: chunked”解决
本文解析了Spring Cloud Gateway中出现“Unsupported transfer encoding: chunked”错误的原因,指出该问题源于Feign依赖的HTTP客户端与服务端的`chunked`传输编码不兼容,并提供了具体的解决方案。通过规范Feign客户端接口的返回类型,可有效避免该异常,提升系统兼容性与稳定性。
201 0
|
6月前
|
前端开发 Java 物联网
智慧班牌源码,采用Java + Spring Boot后端框架,搭配Vue2前端技术,支持SaaS云部署
智慧班牌系统是一款基于信息化与物联网技术的校园管理工具,集成电子屏显示、人脸识别及数据交互功能,实现班级信息展示、智能考勤与家校互通。系统采用Java + Spring Boot后端框架,搭配Vue2前端技术,支持SaaS云部署与私有化定制。核心功能涵盖信息发布、考勤管理、教务处理及数据分析,助力校园文化建设与教学优化。其综合性和可扩展性有效打破数据孤岛,提升交互体验并降低管理成本,适用于日常教学、考试管理和应急场景,为智慧校园建设提供全面解决方案。
400 70
|
4月前
|
缓存 监控 Java
说一说 SpringCloud Gateway 堆外内存溢出排查
我是小假 期待与你的下一次相遇 ~
531 5
|
4月前
|
Java API Nacos
|
10月前
|
JSON Java API
利用Spring Cloud Gateway Predicate优化微服务路由策略
Spring Cloud Gateway 的路由配置中,`predicates`​(断言)用于定义哪些请求应该匹配特定的路由规则。 断言是Gateway在进行路由时,根据具体的请求信息如请求路径、请求方法、请求参数等进行匹配的规则。当一个请求的信息符合断言设置的条件时,Gateway就会将该请求路由到对应的服务上。
759 70
利用Spring Cloud Gateway Predicate优化微服务路由策略
|
8月前
|
前端开发 Java Nacos
🛡️Spring Boot 3 整合 Spring Cloud Gateway 工程实践
本文介绍了如何使用Spring Cloud Alibaba 2023.0.0.0技术栈构建微服务网关,以应对微服务架构中流量治理与安全管控的复杂性。通过一个包含鉴权服务、文件服务和主服务的项目,详细讲解了网关的整合与功能开发。首先,通过统一路由配置,将所有请求集中到网关进行管理;其次,实现了限流防刷功能,防止恶意刷接口;最后,添加了登录鉴权机制,确保用户身份验证。整个过程结合Nacos注册中心,确保服务注册与配置管理的高效性。通过这些实践,帮助开发者更好地理解和应用微服务网关。
1264 0
🛡️Spring Boot 3 整合 Spring Cloud Gateway 工程实践
|
7月前
|
存储 监控 数据可视化
SaaS云计算技术的智慧工地源码,基于Java+Spring Cloud框架开发
智慧工地源码基于微服务+Java+Spring Cloud +UniApp +MySql架构,利用传感器、监控摄像头、AI、大数据等技术,实现施工现场的实时监测、数据分析与智能决策。平台涵盖人员、车辆、视频监控、施工质量、设备、环境和能耗管理七大维度,提供可视化管理、智能化报警、移动智能办公及分布计算存储等功能,全面提升工地的安全性、效率和质量。
128 0
|
9月前
|
监控 JavaScript 数据可视化
建筑施工一体化信息管理平台源码,支持微服务架构,采用Java、Spring Cloud、Vue等技术开发。
智慧工地云平台是专为建筑施工领域打造的一体化信息管理平台,利用大数据、云计算、物联网等技术,实现施工区域各系统数据汇总与可视化管理。平台涵盖人员、设备、物料、环境等关键因素的实时监控与数据分析,提供远程指挥、决策支持等功能,提升工作效率,促进产业信息化发展。系统由PC端、APP移动端及项目、监管、数据屏三大平台组成,支持微服务架构,采用Java、Spring Cloud、Vue等技术开发。
322 7