乐趣区

Spring-Cloud-gateway-网关服务二-断言过滤器

微服务当前这么火爆的程度,如果不能学会一种微服务框架技术。怎么能升职加薪,增加简历的筹码?spring cloud 和 Dubbo 需要单独学习。说没有时间?没有精力?要学俩个框架?而 Spring Cloud alibaba 只需要你学会一个就会拥有俩种微服务治理框架技术。何乐而不为呢?加油吧!骚猿年

上一篇我们讲述了 gateway 的路由功能其实也类似与 zuul 服务的路由转发。
今天主要讲一下断言机制。

内置的断言工厂

介绍 Spring Cloud Gateway 将路由作为 Spring WebFlux HandlerMapping 基础架构的一部分进行匹配。Spring Cloud Gateway 包括许多内置的 Route Predicate 工厂。所有这些断言都与 HTTP 请求的不同属性匹配。多个 Route Predicate 工厂可以合并,也可以通过逻辑合并

可以看到 gateway 提供如此之多丰富的断言,方式。

  • 比如说时间控住的,我们能想到秒杀场景。
  • ip 的我们能想到金丝雀测试
  • 权重我们可以使用灰度等等场景的应用

具体使用还得参照业务场景来选择更适合我们的业务场景。

gateway 过滤器 分为全局过滤器,个性化过滤器

gateway 已经给我们提供了非常丰富的过滤器

  • AddRequestHeader GatewayFilter 工厂采用名称和值参数。

    这会将 X -Request-Foo:Bar 标头添加到所有匹配请求的下游请求的标头中。

    spring:

    cloud:
        gateway:
            routes:
            - id: add_request_header_route
                uri: https://example.org
                filters:
                - AddRequestHeader=X-Request-Foo, Bar
    
    AddRequestHeader 知道用于匹配路径或主机的 URI 变量。URI 变量可用于该值,并将在运行时扩展。spring:
        cloud:
            gateway:
                routes:
                - id: add_request_header_route
                    uri: https://example.org
                    predicates:
                    - Path=/foo/{segment}
                    filters:
                    - AddRequestHeader=X-Request-Foo, Bar-{segment}
    

-AddResponseHeader GatewayFilter 工厂采用名称和值参数。

spring:
    cloud:
        gateway:
            routes:
            - id: add_request_parameter_route
                uri: https://example.org
                filters:
                - AddRequestParameter=foo, bar

这将添加 foo=bar 到所有匹配请求的下游请求的查询字符串中。

AddRequestParameter 知道用于匹配路径或主机的 URI 变量。URI 变量可用于该值,并将在运行时扩展。

spring:
    cloud:
        gateway:
            routes:
            - id: add_request_parameter_route
                uri: https://example.org
                predicates:
                - Host: {segment}.myhost.org
                filters:
                - AddRequestParameter=foo, bar-{segment}
  • AddResponseHeader GatewayFilter 工厂采用名称和值参数。

    spring:

       cloud:
           gateway:
               routes:
               - id: add_response_header_route
                   uri: https://example.org
                   filters:
                   - AddResponseHeader=X-Response-Foo, Bar
               
这会将 X -Response-Foo:Bar 标头添加到所有匹配请求的下游响应的标头中。AddResponseHeader 知道用于匹配路径或主机的 URI 变量。URI 变量可用于该值,并将在运行时扩展。spring:
        cloud:
            gateway:
                routes:
                - id: add_response_header_route
                    uri: https://example.org
                    predicates:
                    - Host: {segment}.myhost.org
                    filters:
                    - AddResponseHeader=foo, bar-{segment}
  • DedupeResponseHeader GatewayFilter 工厂采用一个 name 参数和一个可选 strategy 参数。name 可以包含标题名称列表,以空格分隔。
    spring:

    cloud:
        gateway:
            routes:
            - id: dedupe_response_header_route
                uri: https://example.org
                filters:
                - DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin
    
如果网关 CORS 逻辑和下游逻辑都添加了重复的值 Access-Control-Allow-Credentials 和 Access-Control-Allow-Origin 响应标头,则这将删除它们。DedupeResponseHeader 过滤器还接受可选 strategy 参数。可接受的值为 RETAIN_FIRST(默认值)RETAIN_LAST,和 RETAIN_UNIQUE

  • Hystrix 是 Netflix 的一个库,用于实现断路器模式。Hystrix GatewayFilter 允许您将断路器引入网关路由,保护您的服务免受级联故障的影响,并允许您在下游故障的情况下提供后备响应

    要在项目中启用 Hystrix GatewayFilters,请 spring-cloud-starter-netflix-hystrix 从 Spring Cloud Netflix 添加依赖项。

    Hystrix GatewayFilter 工厂需要一个 name 参数,它是的名称 HystrixCommand。

        spring:
            cloud:
                gateway:
                    routes:
                    - id: hystrix_route
                        uri: https://example.org
                        filters:
                        - Hystrix=myCommandName
                        

这会将其余的过滤器包装在 HystrixCommand 带有命令名的中 myCommandName。

Hystrix 过滤器还可以接受可选 fallbackUri 参数。当前,仅 forward: 支持计划的 URI。如果调用了后备,则请求将被转发到与 URI 相匹配的控制器。


    spring:
        cloud:
            gateway:
                routes:
                - id: hystrix_route
                    uri: lb://backing-service:8088
                    predicates:
                    - Path=/consumingserviceendpoint
                    filters:
                    - name: Hystrix
                        args:
                            name: fallbackcmd
                            fallbackUri: forward:/incaseoffailureusethis
                    - RewritePath=/consumingserviceendpoint, /backingserviceendpoint

/incaseoffailureusethis 调用 Hystrix 后备时,它将转发到 URI。请注意,此示例还通过 lb 目标 URI 上的前缀演示了(可选)Spring Cloud Netflix Ribbon 负载平衡。

主要方案是对 fallbackUri 网关应用程序中的内部控制器或处理程序使用。但是,也可以将请求重新路由到外部应用程序中的控制器或处理程序,如下所示:



    spring:
        cloud:
            gateway:
                routes:
                - id: ingredients
                    uri: lb://ingredients
                    predicates:
                    - Path=//ingredients/**
                    filters:
                    - name: Hystrix
                        args:
                            name: fetchIngredients
                            fallbackUri: forward:/fallback
                - id: ingredients-fallback
                    uri: http://localhost:9994
                    predicates:
                    - Path=/fallback

在此示例中,fallback 网关应用程序中没有终结点或处理程序,但是另一个应用程序中有一个终结点或处理程序,在下注册 localhost:9994。

如果将请求转发给后备,则 Hystrix 网关过滤器还会提供 Throwable 引起请求的。它已 ServerWebExchange 作为 ServerWebExchangeUtils.HYSTRIX_EXECUTION_EXCEPTION_ATTR 属性添加到,可以在网关应用程序中处理后备时使用。

对于外部控制器 / 处理程序方案,可以添加带有异常详细信息的标头。您可以在 FallbackHeaders GatewayFilter Factory 部分中找到有关它的更多信息。

Hystrix 设置(例如超时)可以使用全局默认值配置,也可以使用 Hystrix Wiki 上说明的应用程序属性在逐条路由的基础上进行配置。

要为上述示例路由设置 5 秒超时,将使用以下配置:

hystrix.command.fallbackcmd.execution.isolation.thread.timeoutInMilliseconds: 5000

  • 该 FallbackHeaders 工厂可以让你在转发到请求的头部添加猬执行异常的详细信息 fallbackUri 在以下情况下在外部应用程序
    spring:

    cloud:
        gateway:
            routes:
            - id: ingredients
                uri: lb://ingredients
                predicates:
                - Path=//ingredients/**
                    filters:
                    - name: Hystrix
                        args:
                            name: fetchIngredients
                            fallbackUri: forward:/fallback
                - id: ingredients-fallback
                    uri: http://localhost:9994
                    predicates:
                    - Path=/fallback
                    filters:
                    - name: FallbackHeaders
                        args:
                            executionExceptionTypeHeaderName: Test-Header
                            
                            

在此示例中,在运行时发生执行异常后 HystrixCommand,该请求将转发到在上 fallback 运行的应用中的端点或处理程序 localhost:9994。具有异常类型,消息和 -if available- 根本原因异常类型和消息的标头将由 FallbackHeaders 过滤器添加到该请求。

通过设置下面列出的参数的值及其默认值,可以在配置中覆盖标头的名称:

- executionExceptionTypeHeaderName("Execution-Exception-Type")- executionExceptionMessageHeaderName("Execution-Exception-Message")- rootCauseExceptionTypeHeaderName("Root-Cause-Exception-Type")- rootCauseExceptionMessageHeaderName("Root-Cause-Exception-Message")

您可以在 Hystrix GatewayFilter Factory 部分中找到有关 Hystrix 如何与 Gateway 一起工作的更多信息。

  • MapRequestHeader GatewayFilter 工厂采用 ’fromHeader’ 和 ’toHeader’ 参数。它创建一个新的命名标头(toHeader),并从传入的 HTTP 请求中从现有的命名标头(fromHeader)中提取值。如果输入标头不存在,则过滤器不起作用。如果新的命名标头已经存在,则其值将使用新值进行扩充。

    spring:

    cloud:
        gateway:
            routes:
            - id: map_request_header_route
                uri: https://example.org
                filters:
                - MapRequestHeader=Bar, X-Request-Foo
    

这会将 X -Request-Foo:<values> 标头添加到下游请求的标头中,其中包含来自传入的 HTTP 请求 Bar 标头的更新值。

  • PrefixPath GatewayFilter 工厂采用单个 prefix 参数。
    spring:

    cloud:
        gateway:
            routes:
            - id: prefixpath_route
                uri: https://example.org
                filters:
                - PrefixPath=/mypath
    

这将 /mypath 作为所有匹配请求的路径的前缀。因此,对的请求 /hello 将发送给 /mypath/hello。

  • PreserveHostHeader GatewayFilter 工厂没有参数。此过滤器设置请求属性,路由过滤器将检查该请求属性,以确定是否应发送原始主机头,而不是由 HTTP 客户端确定的主机头。

    spring:

    cloud:
        gateway:
            routes:
            - id: preserve_host_route
                uri: https://example.org
                filters:
                - PreserveHostHeader
  • RequestRateLimiter GatewayFilter Factory 使用一种 RateLimiter 实现来确定是否允许继续当前请求。如果不是,HTTP 429 – Too Many Requests 则返回状态(默认)。此过滤器采用一个可选 keyResolver 参数和特定于速率限制器的参数。
  • Redis RateLimiter GatewayFilter 工厂 redis 实现基于 Stripe 所做的工作。它需要使用 spring-boot-starter-data-redis-reactiveSpring Boot 启动器。
  • RedirectTo GatewayFilter 工厂采用 status 和 url 参数。状态应该是 300 系列重定向 http 代码,例如 301。URL 应该是有效的 URL。这将是 Location 标题的值
  • RemoveHopByHopHeadersFilter GatewayFilter 工厂从转发的请求中删除标头。被删除的头的默认列表来自 IETF。
  • RemoveRequestHeader GatewayFilter 工厂采用一个 name 参数。它是要删除的标题的名称。
  • RemoveResponseHeader GatewayFilter 工厂采用一个 name 参数。它是要删除的标题的名称。
  • RemoveRequestParameter GatewayFilter 工厂采用一个 name 参数。它是要删除的查询参数的名称。
  • RewritePath GatewayFilter 工厂采用路径 regexp 参数和 replacement 参数。这使用 Java 正则表达式提供了一种灵活的方式来重写请求路径。
  • RewriteLocationResponseHeader GatewayFilter 工厂 Location 通常会修改响应标头的值,以摆脱后端特定的详细信息。这需要 stripVersionMode,locationHeaderName,hostValue,和 protocolsRegex 参数。
  • 该 RewriteResponseHeader GatewayFilter 厂需要 name,regexp 和 replacement 参数。它使用 Java 正则表达式以灵活的方式重写响应标头值。
  • SaveSession GatewayFilter Factory 在向下游转发呼叫之前强制执行 WebSession::save 操作。这在将 Spring Session 之类的东西与惰性数据存储一起使用时特别有用,并且需要确保在进行转发呼叫之前已保存会话状态。
  • SetPath GatewayFilter 工厂采用路径 template 参数。通过允许路径的模板段,它提供了一种操作请求路径的简单方法。这使用了 Spring Framework 中的 uri 模板。允许多个匹配段。
  • SetRequestHeader GatewayFilter 工厂采用 name 和 value 参数。
  • SetResponseHeader GatewayFilter 工厂采用 name 和 value 参数
  • SetStatus GatewayFilter 工厂采用单个 status 参数。它必须是有效的 Spring HttpStatus。它可以是整数值 404 或枚举的字符串表示形式 NOT_FOUND
  • StripPrefix GatewayFilter 工厂采用一个参数 parts。该 parts 参数指示在向下游发送请求之前,要从请求中剥离的路径中的零件数
  • 重试 GatewayFilter 工厂
  • RequestSize GatewayFilter 工厂 当请求大小大于允许的限制时,RequestSize GatewayFilter Factory 可以限制请求到达下游服务。过滤器将 RequestSize 参数作为请求的允许大小限制(以字节为单位
  • 修改请求正文 GatewayFilter 工厂 该过滤器被认为是 BETA,API 将来可能会更改 此过滤器可用于在网关将请求主体发送到下游之前修改请求主体。
  • 默认过滤器 如果您想添加过滤器并将其应用于所有路由,则可以使用 spring.cloud.gateway.default-filters。该属性采用过滤器列表
  • 全局过滤器 该 GlobalFilter 接口具有与相同的签名 GatewayFilter。这些是特殊过滤器,有条件地应用于所有路由。(此界面和用法可能会在将来的里程碑中更改)。
  • 全局过滤器和 GatewayFilter 的组合订购

因为 spring cloud gateway 提供的内置过滤器太多了。不在这里一一介绍
可以查看官方的文档 进行了解学习

gateway 官方文档

https://cloud.spring.io/sprin…

接下来讲一下,全局过滤器 GlobalFilter 接口。

  • GlobalFilter 和 GatewayFilter 的 #filter(ServerWebExchange, GatewayFilterChain) 方法签名一致;
  • GlobalFilter 会作用于所有的路由上;
  • 在未来的里程碑版本中可能作一些调整;

可以看一下默认的实现的全局过滤器,除去 AuthorizeFilter 过滤器都是默认的过滤器

具体的里面的作用,其实上面的已经有了简单的描述不在复述。有兴趣的同学可以看看里面的实现,都是利用过滤器做转发或者一些对流量请求的修改、鉴权、等操作

可以通过 actuator 模块监控查询 GlobalFilter 实现类

1、pom 引入 spring-boot-starter-actuator。因为之前就直接在 parent pom 进行了引入操作。不再次引入

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

2、配置文件 bootstrap.yml 中开启监控管理端点


management:
  endpoints:
    web:
      exposure:
        include: "*"
  endpoint:
    health:
      show-details: ALWAYS

3、请求浏览器 http://localhost:9000/actuator/gateway/globalfilters

{
org.springframework.cloud.gateway.filter.AdaptCachedBodyGlobalFilter@4b957db0: -2147482648,
org.springframework.cloud.gateway.filter.WebsocketRoutingFilter@273fa9e: 2147483646,
com.xian.cloud.filter.AuthorizeFilter@4b03cbad: 0,
org.springframework.cloud.gateway.filter.ForwardRoutingFilter@8840c98: 2147483647,
org.springframework.cloud.gateway.filter.NettyRoutingFilter@5c313224: 2147483647,
org.springframework.cloud.gateway.filter.NettyWriteResponseFilter@1e1e837d: -1,
org.springframework.cloud.gateway.filter.RouteToRequestUrlFilter@5d71b500: 10000,
org.springframework.cloud.gateway.filter.LoadBalancerClientFilter@5b29ab61: 10100,
org.springframework.cloud.gateway.filter.GatewayMetricsFilter@527a8665: -2147473648,
org.springframework.cloud.gateway.filter.ForwardPathFilter@626b639e: 0
}

观察这些实现类。都是实现 GlobalFilter、Ordered 俩个接口
实现自己的全局过滤器

创建 AuthorizeFilter

package com.xian.cloud.filter;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 * <Description>
 *
 * @author xianliru@100tal.com
 * @version 1.0
 * @createDate 2019/11/04 18:06
 */
@Component
@Slf4j
public class AuthorizeFilter implements GlobalFilter, Ordered {


    private static final String AUTHORIZE_TOKEN = "Authorization";
    private static final String AUTHORIZE_UID = "uid";

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {ServerHttpRequest request = exchange.getRequest();
        HttpHeaders headers = request.getHeaders();

        ServerHttpRequest.Builder mutate = request.mutate();

        String token = headers.getFirst(AUTHORIZE_TOKEN);
        String uid = headers.getFirst(AUTHORIZE_UID);
        String method = request.getMethodValue();

        log.info("AuthorizeFilter token 全局过滤器 token:{},uid:{}",token,uid);
        if (token == null) {token = request.getQueryParams().getFirst(AUTHORIZE_TOKEN);
        }
        if(StringUtils.isNotBlank(token)){//TODO 权限验证}

        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {return 0;}
}

然后启动服务。

curl http://localhost:9000/client/client/test
日志打印

[2019-11-05 19:30:52.802] [INFO] com.xian.cloud.filter.AuthorizeFilter - AuthorizeFilter token 全局过滤器 token:null,uid:null

下一篇我们将介绍定制的过滤器,针对下游服务对应过滤器

摘自参考 spring cloud 官方文档

示例代码地址

服务器 nacos 地址 http://47.99.209.72:8848/nacos

往期地址 spring cloud alibaba 地址

spring cloud alibaba 简介

Spring Cloud Alibaba (nacos 注册中心搭建)

Spring Cloud Alibaba 使用 nacos 注册中心

Spring Cloud Alibaba nacos 配置中心使用

spring cloud 网关服务

Spring Cloud zuul 网关服务 一

Spring Cloud 网关服务 zuul 二

Spring Cloud 网关服务 zuul 三 动态路由

Spring Cloud alibaba 网关 sentinel zuul 四 限流熔断

Spring Cloud gateway 网关服务 一

如何喜欢可以关注分享本公众号。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。转载请附带公众号二维码

退出移动版