SpringCloud GateWay 学习之路(二)

83 阅读5分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第8天,点击查看活动详情

负载均衡

我们只需要在9006中添加lb:// 服务名就可以显示负载均衡,例如 my-cloud-system 的 配置 lb://my-cloud-system

Predicate 断言

断言:当满足条件后才会进行转发路由,如果是多个,那么多个条件需要同时满足

官方提供断言的种类:docs.spring.io/spring-clou…

After

表示配置时间之后才进行转发时间戳获取代码,用于时间代码的获取:

- After=2022-10-25T15:47:07.849+08:00[Asia/Shanghai] #在这个时间之后的请求够可以进行通过,之前的则不能进行访问

Before

匹配ZonedDateTime类型的时间,表示匹配在指定日期时间之前的请求,之后的请求则拒绝404错误

Between

匹配ZonedDateTime类型的时间,由两个ZonedDateTime参数组成,第一个参数为开始时间,第二参数为结束时间,逗号进行分隔

Cookie

由两个参数组成,分别为name(Key)regexp(正则表达式)(Value),匹配具有给定名称且其值与正则表达式匹配的Cookie。

路由规则会通过获取Cookie name值和正则表达式去匹配,如果匹配上就会执行路由,如果匹配不上则不执行。

- Cookie=cook-test,[a-z]+. # 匹配Cookie的key和value(正则表达式)表示任意字母

Header

由两个参数组成,第一个参数为Header名称,第二参数为Header的Value值,指定名称的其值和正则表达式相匹配的Header的请求

Header=headerName, \d+ # \d表示数字

Host

匹配当前请求是否来自于设置的主机。

Host=**.takeoff.com. #匹配当前的主机地址发出的请求

Method

可以设置一个或多个参数,匹配HTTP请求,比如POST,PUT,GET,DELETE

Method=POST,GET. #匹配POST,GET请求

Query

由两个参数组成,第一个为参数名称(必须),第二个为参数值(可选-正则表达式),匹配请求中是否包含第一个参数,如果有两个参数,则匹配请求中第一个参数的值是否符合第二个正则表达式。

Query=id,.+ # 匹配任意请求参数,这里如果需要匹配多个参数,可以写多个- Query=

RemoteAddr

参数由CIDR 表示法(IPv4 或 IPv6)字符串组成,也就是匹配的ID地址,

Weight

需要两个参数group和weight(int)权重数值,实现了路由权重功能,表示将相同的请求根据权重跳转到不同的uri地址,要求group的名称必须一致

    routes:    
        - id: my-cloud-system_high #路由ID,没有固定要求,但是要保证唯一,建议配合服务名
          uri: https://www.baidu.com/
          predicates: # 断言
            - Weight=groupName,8
        - id: my-cloud-system_low #路由ID,没有固定要求,但是要保证唯一,建议配合服务名
          uri: https://www.sogou.com/
          predicates: # 断言
            - Weight=groupName,2

直接访问http://localhost:8200/system/test/test可以看到我们请求的地址成8/2比例交替显示, 80% 的流量转发到www.baidu.com/,将约 20% 的流量转发到www.sogou.com/

Predicate就是为了实现一组匹配规则,让请求过来找到对应的Route进行处理。如果有多个断言则全部命中后进行处理

Filter

路由过滤器允许修改传入的HTTP请求或者返回的HTTP响应,路由过滤器的范围是特定的路由.

Spring Cloud GateWay 内置的Filter生命周期有两种:pre(业务逻辑之前)、post(业务逻辑之后)

GateWay本身自带的Filter分为两种: GateWayFilter(单一)、GlobalFilter(全局)

StripPrefix

StripPrefix 在我们当前请求中,通过规则值去掉某一部分地址,比如我们有一台服务中加入了一个前端nacos-provider想要通过这个去访问,我们在项目cloud-alibaba-nacos-9001中加入 context-path

server:
  port: 9001
  servlet:
    context-path: /nacos-provider

现在9001的访问路径变为 http://localhost:9001/nacos-provider/mxn/hello,但是如果我们通过网关去访问路径就会变成http://localhost:9006/mxn/nacos-provider/mxn/hello这个时候我们通过这个路径去访问是访问不成功的,想要解决这个方法,这个就用到了我们 FIlter 中的 StripPrefix

      routes:
        - id: my-cloud-system
          uri: lb://my-cloud-system
          predicates:
            - Path=/system/**
          filters:
            - StripPrefix=1 # 去掉地址中的第一部分

原来请求地址 http://localhost:8200/system/test/test 变为。 http://localhost:8200/test/test

自定义Filter

虽然Gateway给我们提供了丰富的内置Filter,但是实际项目中,自定义Filter的场景非常常见,因此单独介绍下自定义FIlter的使用。

想要实现GateWay自定义过滤器,那么我们需要实现 GatewayFilter 接口和 Ordered 接口

@Slf4j
@Component
public class TestFilter implements Ordered, GlobalFilter {
    /**
     * @Author: Take-off
     * @Description: //TODO 过滤器-根据拿到的request和response  return 是否放行
     * @Date: 9:20 PM 2022/10/24
     **/
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //获取参数
        String id = exchange.getRequest().getQueryParams().getFirst("id");
        log.info("TestFilter请求时间:"+ new Date() + "--请求Id:" + id);
        if(StringUtils.isEmpty(id)){
            log.info("用户名不存在,非法请求!");
            //如果username为空,返回状态码为401,需要代理身份验证
            exchange.getResponse().setStatusCode(HttpStatus.PROXY_AUTHENTICATION_REQUIRED);
            // 后置过滤器
            return exchange.getResponse().setComplete();
        }
        return chain.filter(exchange);
    }
    /**
     * @Author: Take-off
     * @Description: //TODO 设定过滤器优先级,指越小优先级越高
     * @Date: 9:21 PM 2022/10/24
     **/
    @Override
    public int getOrder() {
        return 0;
    }
}

总结

对于GateWay的核心点主要有三个 Route、Predicate、Filter,我们搞懂了这三点,基本上对于GateWay的知识就掌握的差不多了,GateWay核心的流程就是:路由转发+执行过滤器链