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工厂可以合并,也可以通过逻辑合并

Spring Cloud gateway 网关服务二 断言、过滤器_第1张图片

可以看到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: 标头添加到下游请求的标头中,其中包含来自传入的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/spring-cloud-gateway/reference/html/

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

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

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

Spring Cloud gateway 网关服务二 断言、过滤器_第2张图片

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

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

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


    org.springframework.boot
    spring-boot-starter-actuator

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;

/**
 * 
 *
 * @author [email protected]
 * @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 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 网关服务 一

如何喜欢可以关注分享本公众号。
Spring Cloud gateway 网关服务二 断言、过滤器_第3张图片

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

你可能感兴趣的:(Spring Cloud gateway 网关服务二 断言、过滤器)