gateway网关官方文档: https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#

网关的概念

网关作为流量的入口,常用的功能包括路由转发,权限校验,限流等。
Spring Cloud Gateway 是Spring Cloud官方推出的第二代网关框架,定位于取代 Netflix Zuul。相比 Zuul 来说,Spring Cloud Gateway 提供更优秀的性能,更强大的功能。Spring Cloud Gateway 是由 WebFlux + Netty + Reactor 实现的响应式的 API 网关。它不能在传统的 servlet 容器中工作,也不能构建成 war 包。Spring Cloud Gateway 旨在为微服务架构提供一种简单且有效的 API 路由的管理方式,并基于 Filter 的方式提供网关的基本功能,例如说安全认证、监控、限流等等。

核心概念

路由(route)

路由是网关中最基础的部分,路由信息包括一个ID、一个目的URI、一组断言工厂、一组Filter组成。如果断言为真,则说明请求的URL和配置的路由匹配。

断言(predicates)

Java8中的断言函数,SpringCloud Gateway中的断言函数类型是Spring5.0框架中的ServerWebExchange。断言函数允许开发者去定义匹配Httprequest中的任何信息,比如请求头和参数等。

过滤器(Filter)

SpringCloud Gateway中的filter分为Gateway FilIer和Global Filter。Filter可以对请求和响应进行处理

工作原理

Spring Cloud Gateway 的工作原理跟 Zuul 的差不多,最大的区别就是 Gateway 的 Filter 只有 pre 和 post 两种。
在这里插入图片描述
客户端向 Spring Cloud Gateway 发出请求,如果请求与网关程序定义的路由匹配,则该请求就会被发送到网关 Web 处理程序,此时处理程序运行特定的请求过滤器链。
过滤器之间用虚线分开的原因是过滤器可能会在发送代理请求的前后执行逻辑。所有 pre 过滤器逻辑先执行,然后执行代理请求;代理请求完成后,执行 post 过滤器逻辑。

路由断言工厂(Route Predicate Factories)配置

具体参考gateway官网给的示例: Route Predicate Factories
主要包含一些:时间匹配 路径匹配 cookie配置 Header匹配 query查询条件匹配等

# 核心概念1:路由,一个路由代表一个处理逻辑,
      # 该逻辑里面包含三个元素:匹配条件(是否该此路由处理)、真实处理地址、过滤器
      routes:
        # id要确保唯一性
      - id: add_request_header_route
      	# 真实处理地址,请求一旦确定是当前路由处理,就会转发到这个地址去
        uri: https://example.org
        # 核心概念2:谓语或者断言,作用是判断请求是否由当前路由处理
        predicates:
          # 这是断言的一种,检查请求的Cookie中mycookie的值是否等于mycookievalue
        - Cookie=mycookie,mycookievalue
        # 核心概念3:过滤器,请求前和请求后都可以有过滤器处理请求响应数据
        filters:
          # 这个过滤器的作用是在请求header中添加一个键值对,值等于"aaabbbccc"
        - AddRequestHeader=X-Request-Red, aaabbbccc

自定义路由工厂

自定义路由断言工厂需要继承 AbstractRoutePredicateFactory 类,重写 apply 方法的逻辑。在 apply 方法中可以通过 exchange.getRequest() 拿到 ServerHttpRequest 对象,从而可以获取到请求的参数、请求方式、请求头等信息。
注意: 命名需要以 RoutePredicateFactory 结尾

@Component
@Slf4j
public class CheckAuthRoutePredicateFactory extends AbstractRoutePredicateFactory<CheckAuthRoutePredicateFactory.Config> {

    public CheckAuthRoutePredicateFactory() {
        super(Config.class);
    }
    @Override
    public Predicate<ServerWebExchange> apply(Config config) {
        return new GatewayPredicate() {
            @Override
            public boolean test(ServerWebExchange serverWebExchange) {
                log.info("调用CheckAuthRoutePredicateFactory" + config.getName());
                if(config.getName().equals("fox")){
                    return true;
                }
                return false;
            }
        };
    }

在yaml配置文件中引入自定义的路由工厂

spring:
  cloud:
    gateway:
      #设置路由:路由id、路由到微服务的uri、断言
      routes:
      - id: order_route  #路由ID,全局唯一
        uri: http://localhost:8020  #目标微服务的请求地址和端口
        predicates:
         # 测试:http://localhost:8888/order/findOrderByUserId/1
           - Path=/order/**   #Path路径匹配
        #自定义CheckAuth断言工厂
#        - name: CheckAuth
#          args:
#            name: fox
        - CheckAuth=fox   

过滤器工厂( GatewayFilter Factories)配置

gateway官方示例: GatewayFilter Factories
SpringCloudGateway 内置了很多的过滤器工厂,我们通过一些过滤器工厂可以进行一些业务逻辑处理器,比如添加剔除响应头,添加去除参数,添加请求头,为匹配的路由统一添加前缀,重定向操作等

spring:
  cloud:
    gateway:
      #设置路由:路由id、路由到微服务的uri、断言
      routes:
      - id: order_route  #路由ID,全局唯一
        uri: http://localhost:8020  #目标微服务的请求地址和端口
        #配置过滤器工厂
        filters:
        - PrefixPath=/mall-order  # 添加前缀 对应微服务需要配置context-path

讲解以下 The RequestRateLimiter GatewayFilter Factory过滤工厂,它可以完成请求的限流,在实际开发中处理网关限流的时候就需要配置

RequestRateLimiter GatewayFilter工厂使用一个RateLimiter实现来确定当前请求是否允许继续。如果不是,返回HTTP 429 - Too Many Requests(默认情况下)的状态。
该过滤器接受一个可选的keyResolver参数和特定于速率限制器的参数
keyResolver是一个实现keyResolver接口的bean。在配置中,使用SpEL按名称引用bean。#{@myKeyResolver}是一个SpEL表达式,它引用了一个名为myKeyResolver的bean。KeyResolver接口如下所示:

public interface KeyResolver {

	Mono<String> resolve(ServerWebExchange exchange);

}

KeyResolver接口允许可插入策略派生限制请求key。在未来的里程碑版本中,将会有一些KeyResolver实现。当前的默认实现类是PrincipalNameKeyResolver ,它从ServerWebExchange检索Principal并调用Principal. getname()。
默认情况下,如果KeyResolver没有找到key,请求将被拒绝。你可以通过设置
spring.cloud.gateway.filter.request-rate-limiter.deny-empty-key (true或false)和spring.cloud.gateway.filter.request-rate- limititer来调整这种行为。empty-key-status-code属性。

public class PrincipalNameKeyResolver implements KeyResolver {

	/**
	 * {@link PrincipalNameKeyResolver} bean name.
	 */
	public static final String BEAN_NAME = "principalNameKeyResolver";

	@Override
	public Mono<String> resolve(ServerWebExchange exchange) {
		return exchange.getPrincipal().flatMap(p -> Mono.justOrEmpty(p.getName()));
	}

}

RedisRateLimiter 限流实现

RedisRateLimiter 继承 AbstractRateLimiter
继承RedisRateLimiter  实现自已的redis请求速率

PrefixPath GatewayFilter Factory

PrefixPath GatewayFilter工厂只接受一个前缀参数。配置PrefixPath GatewayFilter的示例如下:

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

这将在所有匹配请求的路径前加上/mypath前缀。因此,对/hello的请求将被发送到/mypath/hello。

StripPrefix GatewayFilter Factory

StripPrefix GatewayFilter工厂接受一个参数parts。parts参数表示在下行发送请求之前从请求中剥离的路径中的部件数量。下面的清单配置了一个StripPrefix GatewayFilter:

spring:
  cloud:
    gateway:
      routes:
      - id: nameRoot
        uri: https://nameservice
        predicates:
        - Path=/name/**
        filters:
        - StripPrefix=2

当通过网关向/name/blue/red发出请求时,向nameservice发出的请求看起来像nameservice/red。

Redis RateLimiter

gateway官网:https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#the-redis-ratelimiter
首先需要引入依赖

  <!--redis限流-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>io.lettuce</groupId>
                    <artifactId>lettuce-core</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

有这么几个属性

redis-rate-limiter.replenishRate  你希望允许用户在不丢弃任何请求的情况下每秒执行多少请求。这是令牌桶被填充的速率。
redis-rate-limiter.burstCapacity  允许用户在一秒钟内执行 的最大请求数。这是令牌桶可以容纳的令牌数量。将该值设置为零将阻止所有请求。
redis-rate-limiter.requestedTokens  是一个请求需要多少令牌。这是为每个请求从桶中提取令牌的数量,默认为1。

一个稳定的速率是通过设置相同的值在replenishRate 和burstCapacity。可以通过将burstCapacity设置为高于supplishrate来允许临时突发。在这种情况下,速率限制器需要被允许在爆发之间有一段时间(根据refreshrate),因为两个连续的爆发将导致丢弃的请求(HTTP 429 - Too Many requests)。下面的清单配置了一个reddis -rate-limit:

1个请求/秒以下的速率限制可以通过设置refreshrate为所需的请求数量,设置requestdtokens为时间间隔,
设置burstCapacity为refreshrate和requestdtokens的乘积来实现,
例如设置refreshrate =1, requestdtokens =60和burstCapacity=60将导致1个请求/分钟的限制。

如:

spring:
  cloud:
    gateway:
      routes:
      - id: requestratelimiter_route
        uri: https://example.org
        filters:
        - name: RequestRateLimiter
          args:
            redis-rate-limiter.replenishRate: 10
            redis-rate-limiter.burstCapacity: 20
            redis-rate-limiter.requestedTokens: 1

自定义配置KeyResolver

@Bean
KeyResolver userKeyResolver() {
    return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("user"));
}

这定义了每个用户10个请求速率的限制。允许20个请求的突发,但是在下一秒,只有10个请求可用。KeyResolver是一个获取用户请求参数的简单方法(注意,不建议在生产环境中使用)。

还可以将速率限制器定义为实现RateLimiter接口的bean。在配置中,您可以使用SpEL按名称引用bean。#{@myRateLimiter}是一个SpEL表达式,它引用了一个名为myRateLimiter的bean。下面的清单定义了一个使用上一个清单中定义的KeyResolver的速率限制器:

spring:
  cloud:
    gateway:
      routes:
      - id: requestratelimiter_route
        uri: https://example.org
        filters:
        - name: RequestRateLimiter
          args:
            rate-limiter: "#{@myRateLimiter}"
            key-resolver: "#{@userKeyResolver}"

RewritePath GatewayFilter factory

RewritePath GatewayFilter factory接受一个路径regexp参数和一个替换参数。它使用Java正则表达式作为重写请求路径的灵活方式。下面的清单配置了一个RewritePath GatewayFilter:

spring:
  cloud:
    gateway:
      routes:
      - id: rewritepath_route
        uri: https://example.org
        predicates:
        - Path=/red/**
        filters:
        - RewritePath=/red/?(?<segment>.*), /$\{segment}

对于/red/blue的请求路径,这将在发出下游请求之前将路径设置为/blue。注意,由于YAML规范的原因, 应该替换为 应该替换为 应该替换为\。

Default Filters

要添加一个过滤器并将其应用于所有路由,你可以使用spring.cloud.gateway.default-filters。此属性接受筛选器列表。下面的清单定义了一组默认过滤器:

spring:
  cloud:
    gateway:
      default-filters:
      - AddResponseHeader=X-Response-Default-Red, Default-Blue
      - PrefixPath=/httpbin

自定义过滤器工厂

继承AbstractNameValueGatewayFilterFactory且我们的自定义名称必须要以GatewayFilterFactory结尾并交给spring管理。

AbstractNameValueGatewayFilterFactory 继承了 AbstractGatewayFilterFactory
@Component
@Slf4j
public class CheckAuthGatewayFilterFactory extends AbstractNameValueGatewayFilterFactory {

    @Override
    public GatewayFilter apply(NameValueConfig config) {
        return (exchange, chain) -> {
            log.info("调用CheckAuthGatewayFilterFactory==="
                    + config.getName() + ":" + config.getValue());
            return chain.filter(exchange);
        };
    }
}

配置自定义过滤器:

spring:
  cloud:
    gateway:
      #设置路由:路由id、路由到微服务的uri、断言
      routes:
      - id: order_route  #路由ID,全局唯一
        uri: http://localhost:8020  #目标微服务的请求地址和端口
        #配置过滤器工厂
        filters:
        - CheckAuth=fox,男
Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐