当前位置:主页 > 查看内容

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

发布时间:2021-05-10 00:00| 位朋友查看

简介:欢迎大家关注我的微信公众号【 老周聊架构 】Java后端主流技术栈的原理、源码分析、架构以及各种互联网高并发、高性能、高可用的解决方案。 一、前言 前几篇我们讲了 Gateway 相应的初始化、路由相关模型以及 Predicate 谓词详解这一篇我们再来讲一下 Filter……

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

一、前言

前几篇我们讲了 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后端主流技术栈的原理、源码分析、架构以及各种互联网高并发、高性能、高可用的解决方案。

在这里插入图片描述
喜欢的话,一键三连走一波。

;原文链接:https://blog.csdn.net/riemann_/article/details/115440231
本站部分内容转载于网络,版权归原作者所有,转载之目的在于传播更多优秀技术内容,如有侵权请联系QQ/微信:153890879删除,谢谢!

推荐图文


随机推荐