美文网首页API网关我爱编程
聊聊spring cloud gateway的GatewayFi

聊聊spring cloud gateway的GatewayFi

作者: go4it | 来源:发表于2018-06-08 22:08 被阅读0次

    本文主要研究一下spring cloud gateway的GatewayFilter

    GatewayFilter

    spring-cloud-gateway-core-2.0.0.RC2-sources.jar!/org/springframework/cloud/gateway/filter/GatewayFilter.java

    /**
     * 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<Void>} to indicate when request processing is complete
         */
        Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain);
    
    }
    

    如注释所说,主要用于类似切面的非功能性需求,比如安全、超时控制等。其直接的实现类为OrderedGatewayFilter、ModifyResponseGatewayFilter、GatewayFilterAdapter

    OrderedGatewayFilter

    spring-cloud-gateway-core-2.0.0.RC2-sources.jar!/org/springframework/cloud/gateway/filter/OrderedGatewayFilter.java

    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;
        }
    
        public GatewayFilter getDelegate() {
            return delegate;
        }
    
        @Override
        public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
            return this.delegate.filter(exchange, chain);
        }
    
        @Override
        public int getOrder() {
            return this.order;
        }
    
        @Override
        public String toString() {
            final StringBuilder sb = new StringBuilder("OrderedGatewayFilter{");
            sb.append("delegate=").append(delegate);
            sb.append(", order=").append(order);
            sb.append('}');
            return sb.toString();
        }
    }
    

    实现了Order接口

    ModifyResponseGatewayFilter

    spring-cloud-gateway-core-2.0.0.RC2-sources.jar!/org/springframework/cloud/gateway/filter/factory/rewrite/ModifyResponseBodyGatewayFilterFactory.java

        public class ModifyResponseGatewayFilter implements GatewayFilter, Ordered {
            private final Config config;
    
            public ModifyResponseGatewayFilter(Config config) {
                this.config = config;
            }
    
            @Override
            @SuppressWarnings("unchecked")
            public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
                ServerHttpResponseDecorator responseDecorator = new ServerHttpResponseDecorator(exchange.getResponse()) {
                    @Override
                    public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
    
                        ResolvableType inElementType = ResolvableType.forClass(config.getInClass());
                        ResolvableType outElementType = ResolvableType.forClass(config.getOutClass());
                        MediaType contentType = exchange.getResponse().getHeaders().getContentType();
                        Optional<HttpMessageReader<?>> reader = getHttpMessageReader(codecConfigurer, inElementType, contentType);
                        Optional<HttpMessageWriter<?>> writer = getHttpMessageWriter(codecConfigurer, outElementType, null);
    
                        if (reader.isPresent() && writer.isPresent()) {
    
                            ResponseAdapter responseAdapter = new ResponseAdapter(body, getDelegate().getHeaders());
    
                            Flux<?> modified = reader.get().read(inElementType, responseAdapter, config.getInHints())
                                    .cast(inElementType.resolve())
                                    .flatMap(originalBody -> Flux.just(config.rewriteFunction.apply(exchange, originalBody)))
                                    .cast(outElementType.resolve());
    
                            return getDelegate().writeWith(
                                    writer.get().write((Publisher)modified, outElementType, null, getDelegate(),
                                            config.getOutHints())
                            );
    
                        }
                        // TODO: error? log?
    
                        return getDelegate().writeWith(body);
                    }
    
                    @Override
                    public Mono<Void> writeAndFlushWith(Publisher<? extends Publisher<? extends DataBuffer>> body) {
                        return writeWith(Flux.from(body)
                                .flatMapSequential(p -> p));
                    }
                };
    
                return chain.filter(exchange.mutate().response(responseDecorator).build());
            }
    
            @Override
            public int getOrder() {
                return NettyWriteResponseFilter.WRITE_RESPONSE_FILTER_ORDER - 1;
            }
    
        }
    

    主要用于修改response

    GatewayFilterAdapter

    spring-cloud-gateway-core-2.0.0.RC2-sources.jar!/org/springframework/cloud/gateway/handler/FilteringWebHandler.java

        private static class GatewayFilterAdapter implements GatewayFilter {
    
            private final GlobalFilter delegate;
    
            public GatewayFilterAdapter(GlobalFilter delegate) {
                this.delegate = delegate;
            }
    
            @Override
            public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
                return this.delegate.filter(exchange, chain);
            }
    
            @Override
            public String toString() {
                final StringBuilder sb = new StringBuilder("GatewayFilterAdapter{");
                sb.append("delegate=").append(delegate);
                sb.append('}');
                return sb.toString();
            }
        }
    

    将GlobalFilter转为GatewayFilter的适配器

    GatewayFilterFactory

    spring-cloud-gateway-core-2.0.0.RC2-sources.jar!/org/springframework/cloud/gateway/filter/factory/GatewayFilterFactory.java

    @FunctionalInterface
    public interface GatewayFilterFactory<C> extends ShortcutConfigurable, Configurable<C> {
    
        String NAME_KEY = "name";
        String VALUE_KEY = "value";
    
        // useful for javadsl
        default GatewayFilter apply(Consumer<C> consumer) {
            C config = newConfig();
            consumer.accept(config);
            return apply(config);
        }
    
        default Class<C> getConfigClass() {
            throw new UnsupportedOperationException("getConfigClass() not implemented");
        }
    
        @Override
        default C newConfig() {
            throw new UnsupportedOperationException("newConfig() not implemented");
        }
    
        GatewayFilter apply(C config);
    
        default String name() {
            //TODO: deal with proxys
            return NameUtils.normalizeFilterFactoryName(getClass());
        }
    
        @Deprecated
        default ServerHttpRequest.Builder mutate(ServerHttpRequest request) {
            return request.mutate();
        }
    }
    

    spring cloud gateway采用工厂模式来生成GatewayFilter,可以看到这里定义了apply方法,根据config来生成GatewayFilter。GatewayFilterFactory有几个抽象类,分别是AbstractGatewayFilterFactory、AbstractNameValueGatewayFilterFactory(继承了AbstractGatewayFilterFactory)、AbstractChangeRequestUriGatewayFilterFactory。

    AbstractGatewayFilterFactory

    spring-cloud-gateway-core-2.0.0.RC2-sources.jar!/org/springframework/cloud/gateway/filter/factory/AbstractGatewayFilterFactory.java

    public abstract class AbstractGatewayFilterFactory<C>
            extends AbstractConfigurable<C> implements GatewayFilterFactory<C> {
    
        @SuppressWarnings("unchecked")
        public AbstractGatewayFilterFactory() {
            super((Class<C>) Object.class);
        }
    
        public AbstractGatewayFilterFactory(Class<C> configClass) {
            super(configClass);
        }
    
        public static class NameConfig {
            private String name;
    
            public String getName() {
                return name;
            }
    
            public void setName(String name) {
                this.name = name;
            }
        }
    }
    

    它的直接实现类如下:

    • HystrixGatewayFilterFactory
    • ModifyRequestBodyGatewayFilterFactory
    • ModifyResponseBodyGatewayFilterFactory
    • PrefixPathGatewayFilterFactory
    • PreserveHostHeaderGatewayFilterFactory
    • RedirectToGatewayFilterFactory
    • RemoveRequestHeaderGatewayFilterFactory
    • RemoveResponseHeaderGatewayFilterFactory
    • RequestRateLimiterGatewayFilterFactory
    • RetryGatewayFilterFactory
    • RewritePathGatewayFilterFactory
    • SaveSessionGatewayFilterFactory
    • SecureHeadersGatewayFilterFactory
    • SetPathGatewayFilterFactory
    • SetStatusGatewayFilterFactory
    • StripPrefixGatewayFilterFactory

    AbstractNameValueGatewayFilterFactory

    spring-cloud-gateway-core-2.0.0.RC2-sources.jar!/org/springframework/cloud/gateway/filter/factory/AbstractNameValueGatewayFilterFactory.java

    public abstract class AbstractNameValueGatewayFilterFactory extends AbstractGatewayFilterFactory<AbstractNameValueGatewayFilterFactory.NameValueConfig> {
    
        public AbstractNameValueGatewayFilterFactory() {
            super(NameValueConfig.class);
        }
    
        public List<String> shortcutFieldOrder() {
            return Arrays.asList(GatewayFilter.NAME_KEY, GatewayFilter.VALUE_KEY);
        }
    
    
        @Validated
        public static class NameValueConfig {
            @NotEmpty
            protected String name;
            @NotEmpty
            protected String value;
    
            public String getName() {
                return name;
            }
    
            public NameValueConfig setName(String name) {
                this.name = name;
                return this;
            }
    
            public String getValue() {
                return value;
            }
    
            public NameValueConfig setValue(String value) {
                this.value = value;
                return this;
            }
    
            @Override
            public String toString() {
                return new ToStringCreator(this)
                        .append("name", name)
                        .append("value", value)
                        .toString();
            }
        }
    }
    

    将泛型限定为AbstractNameValueGatewayFilterFactory.NameValueConfig,其实现类如下:

    • AddRequestHeaderGatewayFilterFactory
    • AddRequestParameterGatewayFilterFactory
    • AddResponseHeaderGatewayFilterFactory
    • SetRequestHeaderGatewayFilterFactory
    • SetResponseHeaderGatewayFilterFactory

    AbstractChangeRequestUriGatewayFilterFactory

    spring-cloud-gateway-core-2.0.0.RC2-sources.jar!/org/springframework/cloud/gateway/filter/factory/AbstractChangeRequestUriGatewayFilterFactory.java

    /**
     * This filter changes the request uri by
     * {@link #determineRequestUri(ServerWebExchange, T)} logic.
     *
     * @author Toshiaki Maki
     */
    public abstract class AbstractChangeRequestUriGatewayFilterFactory<T>
            extends AbstractGatewayFilterFactory<T> {
        private final int order;
    
        public AbstractChangeRequestUriGatewayFilterFactory(Class<T> clazz, int order) {
            super(clazz);
            this.order = order;
        }
    
        public AbstractChangeRequestUriGatewayFilterFactory(Class<T> clazz) {
            this(clazz, RouteToRequestUrlFilter.ROUTE_TO_URL_FILTER_ORDER + 1);
        }
    
        protected abstract Optional<URI> determineRequestUri(ServerWebExchange exchange,
                T config);
    
        public GatewayFilter apply(T config) {
            return new OrderedGatewayFilter((exchange, chain) -> {
                Optional<URI> uri = this.determineRequestUri(exchange, config);
                uri.ifPresent(u -> {
                    Map<String, Object> attributes = exchange.getAttributes();
                    attributes.put(GATEWAY_REQUEST_URL_ATTR, u);
                });
                return chain.filter(exchange);
            }, this.order);
        }
    }
    

    通过GATEWAY_REQUEST_URL_ATTR设置新的uri,其直接实现类为

    • RequestHeaderToRequestUriGatewayFilterFactory(通过header的值来设定uri)

    GatewayFilterFactory.apply

    spring-cloud-gateway-core-2.0.0.RC2-sources.jar!/org/springframework/cloud/gateway/route/RouteDefinitionRouteLocator.java

        private List<GatewayFilter> loadGatewayFilters(String id, List<FilterDefinition> filterDefinitions) {
            List<GatewayFilter> filters = filterDefinitions.stream()
                    .map(definition -> {
                        GatewayFilterFactory factory = this.gatewayFilterFactories.get(definition.getName());
                        if (factory == null) {
                            throw new IllegalArgumentException("Unable to find GatewayFilterFactory with name " + definition.getName());
                        }
                        Map<String, String> args = definition.getArgs();
                        if (logger.isDebugEnabled()) {
                            logger.debug("RouteDefinition " + id + " applying filter " + args + " to " + definition.getName());
                        }
    
                        Map<String, Object> properties = factory.shortcutType().normalize(args, factory, this.parser, this.beanFactory);
    
                        Object configuration = factory.newConfig();
    
                        ConfigurationUtils.bind(configuration, properties,
                                factory.shortcutFieldPrefix(), definition.getName(), validator);
    
                        GatewayFilter gatewayFilter = factory.apply(configuration);
                        if (this.publisher != null) {
                            this.publisher.publishEvent(new FilterArgsEvent(this, id, properties));
                        }
                        return gatewayFilter;
                    })
                    .collect(Collectors.toList());
    
            ArrayList<GatewayFilter> ordered = new ArrayList<>(filters.size());
            for (int i = 0; i < filters.size(); i++) {
                GatewayFilter gatewayFilter = filters.get(i);
                if (gatewayFilter instanceof Ordered) {
                    ordered.add(gatewayFilter);
                }
                else {
                    ordered.add(new OrderedGatewayFilter(gatewayFilter, i + 1));
                }
            }
    
            return ordered;
        }
    

    这里通过factory去实例化每个route的GatewayFilter

    小结

    spring cloud gateway的GatewayFilter主要是通过GatewayFilterFactory来生产的。而GatewayFilterFactory主要有三个抽象类:

    • AbstractGatewayFilterFactory
      • HystrixGatewayFilterFactory
      • ModifyRequestBodyGatewayFilterFactory
      • ModifyResponseBodyGatewayFilterFactory
      • PrefixPathGatewayFilterFactory
      • PreserveHostHeaderGatewayFilterFactory
      • RedirectToGatewayFilterFactory
      • RemoveRequestHeaderGatewayFilterFactory
      • RemoveResponseHeaderGatewayFilterFactory
      • RequestRateLimiterGatewayFilterFactory
      • RetryGatewayFilterFactory
      • RewritePathGatewayFilterFactory
      • SaveSessionGatewayFilterFactory
      • SecureHeadersGatewayFilterFactory
      • SetPathGatewayFilterFactory
      • SetStatusGatewayFilterFactory
      • StripPrefixGatewayFilterFactory
    • AbstractNameValueGatewayFilterFactory(继承了AbstractGatewayFilterFactory)
      • AddRequestHeaderGatewayFilterFactory
      • AddRequestParameterGatewayFilterFactory
      • AddResponseHeaderGatewayFilterFactory
      • SetRequestHeaderGatewayFilterFactory
      • SetResponseHeaderGatewayFilterFactory
    • AbstractChangeRequestUriGatewayFilterFactory
      • RequestHeaderToRequestUriGatewayFilterFactory

    doc

    相关文章

      网友评论

        本文标题:聊聊spring cloud gateway的GatewayFi

        本文链接:https://www.haomeiwen.com/subject/inyxeftx.html