关于java:SpringCloudGateway-网关之我见

3次阅读

共计 11615 个字符,预计需要花费 30 分钟才能阅读完成。

一、概述
在 Spring-Cloud-Gateway 之申请解决流程中最终网关是将申请交给过滤器链表进行解决。
外围接口:GatewayFilter,GlobalFilter,GatewayFilterChain。

二、网关过滤器作用

当应用微服务构建整个 API 服务时,个别有许多不同的利用在运行,如上图所示的 mst-user-service、mst-good-service 和 mst-order-service,这些服务都须要对客户端的申请的进行 Authentication。最简略粗犷的办法就是像上图一样,为每个微服务利用都实现一套用于校验的过滤器或拦截器。
通过前置的网关服务来实现这些非业务性质的校验。

三、Filter 的生命周期
Spring Cloud Gateway 的 Filter 的生命周期有两个:“pre”和“post”。

“pre”和“post”别离会在申请被执行前调用和被执行后调用,和 Zuul Filter 或 Spring Interceptor 中相干生命周期相似,但在模式上有些不一样。
Zuul 的 Filter 是通过 filterType()办法来指定,一个 Filter 只能对应一种类型,要么是“pre”要么是“post”。Spring Interceptor 是通过重写 HandlerInterceptor 中的三个办法来实现的。而 Spring Cloud Gateway 基于 Project Reactor 和 WebFlux,采纳响应式编程格调,关上它的 Filter 的接口 GatewayFilter 你会发现它只有一个办法 filter。
四、外围接口解读
4.1、GatewayFilterChain– 网关过滤链表
/**

  • 网关过滤链表接口
  • 用于过滤器的链式调用
    */

public interface GatewayFilterChain {

/**
 *  链表启动调用入口办法 */
Mono<Void> filter(ServerWebExchange exchange);
} 

默认实现

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

    /**
     * 以后过滤执行过滤器在汇合中索引
     */
    private final int index;
    /**
     * 过滤器汇合
     */
    private final List<GatewayFilter> filters;

    public DefaultGatewayFilterChain(List<GatewayFilter> 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<GatewayFilter> getFilters() {return filters;}

    /**
     * @param exchange the current server exchange
     * @return
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange) {return Mono.defer(() -> {if (this.index < filters.size()) {
                // 获取以后索引的过滤器
                GatewayFilter filter = filters.get(this.index);
                // 构建以后索引的下一个过滤器的 FilterChain
                DefaultGatewayFilterChain chain = new DefaultGatewayFilterChain(this, this.index + 1);
                // 调用过滤器的 filter 办法执行过滤器
                return filter.filter(exchange, chain);
            } else {
                // 以后索引大于等于过滤汇合大小,标识所有链表都已执行结束,返回空
                return Mono.empty(); // complete}
        });
    }
}

过滤器的 GatewayFilterChain 执行程序
通过 GatewayFilter 汇合构建顶层的 GatewayFilterChain 调用顶层 GatewayFilterChain,获取第一个 Filter,并创立下一个 Filter 索引对应的 GatewayFilterChain 调用 filter 的 filter 办法执行以后 filter,并将下次要执行的 filter 对应 GatewayFilterChain 传入。
4.2、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
    *
    */

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);

}

网关过滤器接口,有且只有一个办法 filter,执行以后过滤器,并在此办法中决定过滤器链表是否持续往下执行。
1️⃣、OrderedGatewayFilter– 排序
/**

  • 排序的网关路由过滤器,用于包装实在的网关过滤器,已达到过滤器可排序
    */

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<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {return this.delegate.filter(exchange, chain);
}

}

OrderedGatewayFilter 实现类次要目标是为了将指标过滤器包装成可排序的对象类型。是指标过滤器的包装类
2️⃣、GatewayFilterAdapter
/**

 * 全局过滤器的包装类,将全局路由包装成对立的网关过滤器
 */
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);
    }
}

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

GlobalFilter 为申请业务以及路由的 URI 转换为实在业务服务的申请地址的外围过滤器,不须要配置,模式零碎初始化时加载,并作用在每个路由上。
1️⃣、初始化加载,通过 GatewayAutoConfiguration 主动创立

//GatewayAutoConfiguration 类

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

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

//GatewayLoadBalancerClientAutoConfiguration 类

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

2️⃣、GlobalFilter 转换成 GatewayFilter,并作用于每个路由上,在 FilteringWebHandler 实现
//FilteringWebHandler 类

/**
 * 包装加载全局的过滤器,将全局过滤器包装成 GatewayFilter
 */
private static List<GatewayFilter> loadFilters(List<GlobalFilter> 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<Void> handle(ServerWebExchange exchange) {
    // 获取申请上下文设置的路由实例
    Route route = exchange.getRequiredAttribute(GATEWAY_ROUTE_ATTR);
    // 获取路由定义下的网关过滤器汇合
    List<GatewayFilter> gatewayFilters = route.getFilters();

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

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

loadFilters 办法是将全局路由应用 GatewayFilterAdapter 包装成 GatewayFilterhandle 办法
获取以后申请应用的路由 Route 获取路由配置的过滤器汇合 route.getFilters()合并全过滤器与路由配置过滤器 combined 对过滤器排序 AnnotationAwareOrderComparator.sort 通过过滤器汇合构建顶级链表 DefaultGatewayFilterChain,并对其以后申请调用链表的 filter 办法。
小结
Spring-Cloud-Gateway 的过滤器接口分为两种:
GlobalFilter : 全局过滤器,不须要在配置文件中配置,作用在所有的路由上,最终通过 GatewayFilterAdapter 包装成 GatewayFilterChain 可辨认的过滤器 GatewayFilter : 须要通过 spring.cloud.routes.filters 配置在具体路由下,只作用在以后路由上或通过 spring.cloud.default-filters 配置在全局,作用在所有路由上
五、GatewayFilterFactory 配置路由过滤器
路由过滤器容许以某种形式批改传入的 HTTP 申请或传出的 HTTP 响应。门路过滤器的范畴限定为特定门路。
1️⃣、加载 GatewayFilter
在路由定位器中以及看到了通过路由定义转换路由办法,其中蕴含了通过过滤器定义 (FilterDefinition) 转换过滤器 (GatewayFilter) 的局部, 在 RouteDefinitionRouteLocator 类中源码如下:
/**

 * 加载过滤器,依据过滤器的定义加载
 */
@SuppressWarnings("unchecked")
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());
                }

                // 依据 args 组装配置信息
                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 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());
    // 包装过滤器使其所有过滤器继承 Ordered 属性,可进行排序
    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;
}

/**
 * 获取 RouteDefinition 中的过滤器汇合
 */
private List<GatewayFilter> getFilters(RouteDefinition routeDefinition) {List<GatewayFilter> filters = new ArrayList<>();

    // 校验 gatewayProperties 是否含意默认的过滤器汇合
    //TODO: support option to apply defaults after route specific filters?
    if (!this.gatewayProperties.getDefaultFilters().isEmpty()) {
        // 加载全局配置的默认过滤器汇合
        filters.addAll(loadGatewayFilters("defaultFilters",
                this.gatewayProperties.getDefaultFilters()));
    }

    if (!routeDefinition.getFilters().isEmpty()) {
        // 加载路由定义中的过滤器汇合
        filters.addAll(loadGatewayFilters(routeDefinition.getId(), routeDefinition.getFilters()));
    }

    // 排序
    AnnotationAwareOrderComparator.sort(filters);
    return filters;
}

getFilters 办法 合并配置中的全局过滤器与路由本身配置的过滤器,并对其排序(全局配置过滤器信息通过 gatewayProperties.getDefaultFilters()获取)loadGatewayFilters 顺次遍历路由定义下的 FilterDefinition 并将其通过对应的 GatewayFilterFactory 转换为 GatewayFilter 对象。
2️⃣、GatewayFilterFactory 配置过滤器创立工厂创立 GatewayFilter 对象
默认内置很多 GatewayFilterFactory 实现类,用于创立作用不同的网关过滤器。
类图

子类及其划分

3️⃣、AddResponseHeaderGatewayFilterFactory 创立解析
/**
*

  • 响应 header 增加数据过滤器
  • 用户在 response header 中增加配置数据
    */

public class AddResponseHeaderGatewayFilterFactory extends AbstractNameValueGatewayFilterFactory {

@Override
public GatewayFilter apply(NameValueConfig config) {return (exchange, chain) -> {
        // 获取 Response 并将配置的数据增加到 header 中
        exchange.getResponse().getHeaders().add(config.getName(), config.getValue());

        return chain.filter(exchange);
    };
}

}。

配置示例:
spring:
cloud:

gateway:
  default-filters:
  - AddResponseHeader=X-Response-Default-Foo, Default-Bar 

AddResponseHeader=X-Response-Default-Foo, Default-Bar
会被解析成 FilterDefinition 对象(name =AddResponseHeader,args=
[X-Response-Default-Foo,Default-Bar])通 FilterDefinition 的 Name 找到 AddResponseHeaderGatewayFilterFactory 工厂通过 FilterDefinition 的 args 创立 Config 对象(name=X-Response-Default-Foo,value=Default-Bar)通过 AddResponseHeaderGatewayFilterFactory 工厂的 apply 办法传入 config 创立 GatewayFilter 对象。
4️⃣、全副配置
5.1、申请头

spring:
cloud:

gateway:
  routes:
  - id: add_request_header_route
    uri: http://example.org
    filters:
    - AddRequestHeader=X-Request-Foo, Bar 

名称和值,这将为所有匹配申请的上游申请标头增加 X -Request-Foo:Bar 标头。
移除申请头

    filters:
    - RemoveRequestHeader=X-Request-Foo 

5.2、申请参数

    filters:
    - AddRequestParameter=foo, bar 

这会将 foo = bar 增加到上游申请的所有匹配申请的查问字符串中。
5.3、增加响应头

    filters:
    - AddResponseHeader=X-Response-Foo, Bar 

这会将 X -Response-Foo:Bar 标头增加到所有匹配申请的上游响应标头中。
移除响应头

    filters:
    - RemoveResponseHeader=X-Response-Foo 

设置响应头

    filters:
    - SetResponseHeader=X-Response-Foo, Bar 

此 GatewayFilter 将替换具备给定名称的所有标头,而不是增加。
5.4、门路前缀

    filters:
    - PrefixPath=/mypath 

这将使 / mypath 前缀为所有匹配申请的门路。所以对 / hello 的申请会被发送到 / mypath / hello。
5.5、原始主机头
没有参数,此过滤器设置路由过滤器将查看的申请属性,以确定是否应发送原始主机头,而不是 http 客户端确定的主机头。

    filters:
    - PreserveHostHeader 

5.6、重定向

    filters:
    - RedirectTo=302, http://acme.org 

这将发送带有 Location:http://acme.org 标头的状态 302 以执行重定向。
5.7、重写门路

    predicates:
    - Path=/foo/**
    filters:
    - RewritePath=/foo/(?<segment>.*), /$\{segment} 

对于 / foo / bar 的申请门路,这将在收回上游申请之前将门路设置为 / bar。留神因为 YAML 标准,$ \ 替换为 $。
5.8、保留 Session

    predicates:
    - Path=/foo/**
    filters:
    - SaveSession 

5.9、门路模板
SetPath GatewayFilter Factory 采纳门路模板参数。它提供了一种通过容许模板化门路段来操作申请门路的简略办法。

    predicates:
    - Path=/foo/{segment}
    filters:
    - SetPath=/{segment} 

对于 / foo / bar 的申请门路,这将在收回上游申请之前将门路设置为 / bar。
5.10、设置响应状态
spring:
cloud:

gateway:
  routes:
  - id: setstatusstring_route
    uri: http://example.org
    filters:
    - SetStatus=BAD_REQUEST
  - id: setstatusint_route
    uri: http://example.org
    filters:
    - SetStatus=401 

5.11、申请参数剥离
parts 参数批示在将申请发送到上游之前从申请中剥离的门路中的局部数。

    predicates:
    - Path=/name/**
    filters:
    - StripPrefix=2 

当通过网关向 / name / bar / foo 发出请求时,对 nameservice 的申请将相似于 http:// nameservice / foo。
5.12、重试
retries:重试: 应该尝试的重试次数
statuses:状态: 应该重试的 HTTP 状态代码,应用 org.springframework.http.HttpStatus 示意
methods:办法: 应该重试的 HTTP 办法,应用 org.springframework.http.HttpMethod 示意
series:系列: 要重试的状态代码系列,应用 org.springframework.http.HttpStatus.Series 示意

  routes:
  - id: retry_test
    uri: http://localhost:8080/flakey
    predicates:
    - Host=*.retry.com
    filters:
    - name: Retry
      args:
        retries: 3
        statuses: BAD_GATEWAY 

5.13、Hystrix GatewayFilter Factory
https://cloud.spring.io/spring-cloud-static/Finchley.SR1/sing…
5.14、申请限速 
RequestRateLimiter GatewayFilter Factory
5.15、平安头
SecureHeaders GatewayFilter Factory

正文完
 0