Spring Cloud Gateway详解

Gateway的组成
1️路由(route):路由是网关最基础的部分,路由信息由一个ID,一个目的URL、一组断言工厂和一组Filter组成。如果断言为真,则说明请求URL和配置的路由匹配。

2️断言(Predicate):对请求的各种条件和参数校验,符合条件则放行。Java8中的断言函数,Spring Cloud Gateway中的断言函数输入类型是 Spring5.0框架中的ServerWebExchange。Spring Cloud Gateway中的断言函数允许开发者去定义匹配 来自http Request中的任何信息,比如请求头和参数等。

3️过滤器(Filter):一个标准的Spring WebFilter,Spring Cloud Gateway中的Filter分为两种类型: Gateway Filter和Global Filter。过滤器Filter可以对请求和响应进行处理。对请求和响应的过滤链式处理。Gateway的Filter支持Pre和Post两种模式

配置资源文件
spring:
cloud:
gateway:
discovery:
locator:
#是否与服务发现组件进行结合,通过service-id(必须设置成大写)转发到具体的服务实例。默认false
#为true代表开启基于服务发现的路由规则。
enabled: false
#配置之后访问时service-id无需大写
lower-case-service-id: true
routes:
# 路由标识(id:标识,具有唯一性)
- id: user-consumer-api
#目标服务地址(uri:地址,请求转发后的地址),会自动从注册中心获得服务的IP,不需要手动写死
uri: lb://consumer
#优先级,越小越优先
#order: 999
#路由条件(predicates:断言)
predicates:
# 路径匹配,
- Path=/cum/**
filters:
#路径前缀删除示例:请求/name/bar/foo,StripPrefix=2,去除掉前面两个前缀之后,最后转发到目标服务的路径为/foo
#前缀过滤,请求地址:http://localhost:8084/usr/hello
#此处配置去掉1个路径前缀,再配置上面的 Path=/usr/,就将转发到指定的微服务
#因为这个api相当于是服务名,只是为了方便以后nginx的代码加上去的,对于服务提供者service-client来说,不需要这段地址,所以需要去掉
- StripPrefix=1

Predicate断言
配置到配置文件中, 当满足条件在进行路由转发。
在Spring Cloud Gateway中谓词实现GatewayPredicate接口。其中类名符合:XXXRoutepredicateFactory,其中XXX就是在配置文件中谓词名称。在上面示例中Path=/demo/** 实际上使用的就是PathRoutePredicateFactory

所有的谓词都设置在predicates属性中,当设置多个谓词时取逻辑与条件,且一个谓词只能设置一组条件,如果需要有个多条件,添加多个相同谓词。

1 Query
1.1 设置必须包含的参数名。
下面两种写法等效。都表示路径满足/demo/同时包含参数abc。
Path和Query是谓词。abc是请求参数名称。
在浏览器中输入:http://localhost:9000/demo/one?abc=jqk
predicates: Path=/demo/
,Query=abc
predicates:

  • Path=/demo/** - Query=abc

2 Header
表示请求头中必须包含的内容。
注意:
参数名和参数值之间依然使用逗号
参数值要使用正则表达式
如果Header只有一个值表示请求头中必须包含的参数。如果有两个值,第一个表示请求头必须包含的参数名,第二个表示请求头参数对应值。
predicates:

  • Path=/demo/** - Query=abc,jqk+ - Header=Connection,keep-alive

3 Method
Method表示请求方式。支持多个值,使用逗号分隔,多个值之间为or条件。
predicates:

  • Path=/demo/** - Method=GET,POST

Gateway官方提供了许多的内置断言类型:
After:根据时间进行断言校验,仅指定日期之后才能放行。
Before:和After相反。
Between:在某两个时间之内放行。
Cookie:校验指定的Cookie,符合条件的放行。
Header:校验请求头。
Host:校验匹配当前请求是否来自于设置的主机地址。
Method:匹配HTTP请求方法,例如Post、Get等。
Path:匹配路径。
Query:参数匹配校验。

Filter过滤器
Filter作用:在路由转发到代理服务之前和代理服务返回结果之后额外做的事情。Filter执行了说明谓词条件通过了。

在Spring Cloud Gateway的路由中Filter分为:
内置Filter,都是局部过滤器GatewayFilter实现类, 用于配置到route中
自定义全局过滤器GlobalFilter, 用于开发全局性的逻辑, 优先级通过覆盖getOrder方法, 值越小越高

内置Filter和继承AbstractGatewayFilterFactory的可以用于配置文件中

1 内置Filter
之前使用StripPrefix就是内置Filter,所有内置Filter都实现GatewayFilter接口。使用时filters属性中过滤器名为XXXGatewayFilterFactory的类对应的名称为XXX。

1.1 AddRequestHeader
添加请求头参数,参数和值之间使用逗号分隔
filters:

  • StripPrefix=1 - AddRequestHeader=MyHeader,jqk

1.2 AddRequestParameter
添加请求表单参数,多个参数需要有多个过滤器。
filters:

  • StripPrefix=1 - AddRequestParameter=name,bjsxt - AddRequestParameter=age,123

1.3 AddResponseHeader
添加响应头

1.21 StripPrefix
跳过路由uri中前几段后发送给下游

使用Gateway实现限流
可以利用Gateway中RequestRateLimiter实现限流。
RequestRateLimiter是基于Redis和Lua脚本实现的令牌桶算法。

使用Gateway实现服务降级
Spring Cloud Gateway 可以利用Hystrix实现服务降级等功能。

GlobalFilter
开发程序用来过滤, 比如过滤登录
全局过滤器不需要工厂,也不需要配置,直接对所有的路由都生效。
可以使用GlobalFilter实现统一的权限验证、日志记录等希望对所有代理的项目都生效的内容都可以配置在全局过滤器中。
且在项目中可以配置多个GlobalFilter的实现类。都可以自动执行

自定义全局过滤器需要实现GlobalFilter、Ordered 接口。在getOrdered方法中返回过滤器执行的优先级,在filter 方法中编写执行逻辑。
return chain.filter(exchange): 表示继续向后执行。
return exchange.getResponse().setComplete(): 表示拦截停止执行立即请求返回。

自定义FilterFactory
可以定义针对于Router的Filter。
注意:

  1. 类名必须叫做XXXGatewayFilterFactory.注入到Spring容器后使用时的名称就叫做XXX。
  2. 类必须继承AbstractGatewayFilterFactory
  3. 所有需要传递进来的参数都配置到当前类的内部类Config中

代码示例
局部过滤器和全局过滤器都通过以下方式区分前置还是后置

前置过滤器(请求转发前触发)

@Component
public class GetRecordGatewayFilterFactory extends AbstractGatewayFilterFactory<Object> {
    @Override
    public GatewayFilter apply(Object config) {
        return new DDOSCheckGatewayFilter();
    }

    static class DDOSCheckGatewayFilter implements GatewayFilter, Ordered {
      @Override
      public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
            LoggerUtils.info(LOGGER, "请求转发前触发");
            return chain.filter(exchange);
        }
        @Override
        public int getOrder() {
            return 0;
        }
    }
}

后置过滤器(请求完成后触发)
chain.filter(exchange).then(Mono.fromRunnable(new Runnable() 这行代表这个是后置

@Component
public class GetRecordGatewayFilterFactory extends AbstractGatewayFilterFactory<Object> {
    @Override
    public GatewayFilter apply(Object config) {
        return new DDOSCheckGatewayFilter();
    }

    static class DDOSCheckGatewayFilter implements GatewayFilter, Ordered {
      @Override
      public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
            return chain.filter(exchange).then(Mono.fromRunnable(new Runnable() {
                @Override
                public void run() {
                	LoggerUtils.info(LOGGER, "请求完成后触发");
                }
            }));
        }

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

前置 + 后置过滤器(请求完成后触发)

@Component
public class GetRecordGatewayFilterFactory extends AbstractGatewayFilterFactory<Object> {
    @Override
    public GatewayFilter apply(Object config) {
        return new DDOSCheckGatewayFilter();
    }

    static class DDOSCheckGatewayFilter implements GatewayFilter, Ordered {
      @Override
      public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
            // 进入filter方法,执行chain.filter,都属于请求前阶段
            LoggerUtils.info(LOGGER, "转发请求前触发");
            
            return chain.filter(exchange).then(Mono.fromRunnable(new Runnable() {
                @Override
                public void run() {
                	LoggerUtils.info(LOGGER, "请求完成后触发");
                }
            }));
        }

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

总结
主要就是三部分, 一个路由用来转发请求,
一个断言用来细粒度判断, 根据是否满足断言的条件来进行转发请求,比如请求头中是否包含什么参数,或者cookie等.
一个过滤器分为两种类型, 一种是局部的开发完之后可以配置到route中,来过滤一些特定的数据 一个是全局的, 用来写一些全局逻辑, 比如登录判断. 同时两种都有前置过滤器和后置过滤器的概念, 通过代码编写上来区分, 执行顺序由getOrder方法重新的值决定
chain.filter(exchange)之前就是前置,
chain.filter(exchange).then(Mono.fromRunnable(new Runnable() 里面重新的逻辑就是后置

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值