1. 简介

1.1 概述

SpringCloud Gateway使用的是Webflux中的reactor-netty响应式编程组件,底层使用了Netty通讯框架

image.png
image.png
image.png
image.png

1.2 源码架构

image.png

1.3 作用

  • 反向代理
  • 鉴权
  • 限流
  • 熔断
  • 日志监控
  • ……

    1.4 微服务架构中网关在哪里

    image.png

    2. Zuul与GateWay的区别

    1. netflix不太靠谱,zuul2.0一直跳票,迟迟不发布,且2.0发布后Spring也不集成了…
    2. SpringCloud Gateway模型具有如下特性
      1. image.png
      2. GateWay使用了Spring最新的WebFlux框架,WebFlux基于Netty的异步非阻塞式IO网络模型

    image.png

    1. Zuul1.x模具有如下特性
      1. image.png
      2. image.png
    2. GateWay与Zuul的区别
      1. image.png

2. 三大核心概念

image.png

2.1 Route(路由)

路由是构建网关的基本模块,它由ID,目标URI,一系列的断言和过滤器组成,如断言为true则匹配该路由

2.2 Predicate(断言)

参考的是Java8的java.util.function.Predicate 开发人员可以匹配HTTP请求中的所有内容(请求头、请求方式、Cookie或请求参数等),如果请求与断言相匹配则进行路由

2.3 Filter(过滤)

指的是Spring框架中GatewayFilter的实例,使用过滤器,可以在请求被路由前或路由后对请求进行修改。

3. GateWay的工作流程

核心:路由转发+执行过滤器链 image.png image.png image.png

4. 入门案例

4.1 需求

新建一个9527端口Module做网关,拦截8001payment微服务下的/get/请求和/lb/请求

4.2 依赖

  1. <!--gateway-->
  2. <dependency>
  3. <groupId>org.springframework.cloud</groupId>
  4. <artifactId>spring-cloud-starter-gateway</artifactId>
  5. </dependency>

4.3 yaml

server:
  port: 9527

spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true # 开启从注册中心动态创建路由的功能,利用微服务名称进行路由
      routes:
        - id: payment_route # 路由的id,没有规定规则但要求唯一,建议配合服务名
          # 单实例:匹配后提供服务的路由地址
          uri: http://localhost:8001
          # 多实例,动态路由,使用服务名,需要注意的是uri的协议lb,表示启用Gateway的负载均衡功能.
          #uri: lb://cloud-payment-service
          predicates:
            - Path=/payment/get/** # 断言,路径相匹配的进行路由
        - id: payment_route2
          # 单实例:匹配后提供服务的路由地址
          uri: http://localhost:8001
          # 多实例,动态路由,使用服务名,需要注意的是uri的协议lb,表示启用Gateway的负载均衡功能.
          #uri: lb://cloud-payment-service
          predicates:
            Path=/payment/lb/** #断言,路径相匹配的进行路由

eureka:
  instance:
    hostname: cloud-gateway-service
  client:
    fetch-registry: true
    register-with-eureka: true
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka

4.4 测试

image.png

5. Gateway网关路由的两种配置方式

5.1 yaml配置

参考:4.3 yaml

5.2 代码配置

注入RouteLocator的Bean

/**
 * @author JShawn 2021/3/25 20:02
 */
@Configuration
public class GateWayConfig {

    /**
     * 配置了一个id为path_route_atguigu的路由规则,
     * 当访问地址http://localhost:9527/guonei时会自动转发到地址http://news.baidu.com/guonei
     */
    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
        RouteLocatorBuilder.Builder routes = builder.routes();
        routes.route("path_route_atguigu",r -> r.path("/guonei").uri("http://news.baidu.com/guonei")).build();
        return routes.build();
    }
}

6. 动态路由

由于实际开发中微服务有可能是多实例节点,因此需要通过服务名 spring.application.name 优化配置中写死的uri 默认情况下Gatway会根据注册中心注册的服务列表,以注册中心上微服务名为路径创建动态路由进行转发,从而实现动态路由的功能

6.1 配置

完整配置参考:4.3 yaml中注释的uri多实例部分

# lb://serverName是spring cloud  gatway在微服务中自动为我们创建的负载均衡uri

# 单实例:匹配后提供服务的路由地址
#uri: http://localhost:8001
# 多实例,动态路由,使用服务名,需要注意的是uri的协议lb,表示启用Gateway的负载均衡功能.
uri: lb://cloud-payment-service

7. Predicate

启动gateway时可以看到日志打印如下,这些就是gateway支持的不同方式的断言 image.png

7.1 使用

image.png
image.png

7.2 常用的Route Predicate

常用的Route Predicate 示例 说明
1.After Route Predicate image.png
image.png
某一时间点之后,则执行路由
2.Before Route Predicate 略,参考同上 某一时间点之前,则执行路由
3.Between Route Predicate 略,参考同上 某一时间范围内,则执行路由
4.Cookie Route Predicate image.png
- 不带cookies访问

image.png
- 带上cookies访问
image.png
- 加入curl返回中文乱码
https://blog.csdn.net/leedee/article/details/82685636 | 通过获取对应的Cookie name value和正则表达式去匹配,如果匹配上就会执行路由,如果没有匹配上则不执行 | | 5.Header Route Predicate | image.png
image.png | 两个参数:一个是请求头名称和一个正则表达式,这个属性值和正则表达式匹配则执行 | | 6.Host Route Predicate | image.png | 接收一组匹配的域名列表,这个模板是一个ant分隔的模板,用.号作为分隔符。它通过参数中的主机地址作为匹配规则 | | 7.Method Route Predicate | image.png | 匹配请求方式:GET、POST、PUT、DELETE | | 8.Path Route Predicate | image.png | 路径匹配:路径相同则放行 | | 9.Query Route Predicate |

image.png
image.png
图像.jpeg | 匹配请求参数方式
支持传入两个参数:一个属性名、一个属性值,属性值可以是正则表达式 | | 10.RemoteAddr Route Predicate | | | | 11.Weight Route Predicate | | | | 总结 | | | | 说白了,Predicate就是为了实现一组匹配规则, 让请求过来找到对应的Route进行处理
image.png | | |

8. Filter

image.png

8.1 Spring Cloud Gateway的filter

8.1.1 生命周期

  • pre
  • post

    8.1.2 种类

    8.1.2.1 GatewayFilter

    image.png

    8.1.2.2 GlobalFilter

    image.png

    8.2 常用的GatewayFilter

    8.2.1 AddRequestParameterGateWayFactory

    image.png

    8.2.2 其他省略,主要是自定义

    8.3 自定义Filter

    8.3.1 作用

    全局日志记录、统一网关鉴权、……

8.3.2 自定义全局GlobalFilter

需求:访问接口必须带上uname参数,否则不予访问

8.3.2.1 实现两个接口 GlobalFilter , Ordered

/**
 * @author JShawn 2021/3/25 20:57
 */
@Component
@Slf4j
public class MyLogGatewayFilter implements GlobalFilter, Ordered {

    /**
     * 过滤逻辑
     * @param exchange
     * @param chain
     * @return
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        log.info("come in global filter: {}", new Date());

        ServerHttpRequest request = exchange.getRequest();
        String uname = request.getQueryParams().getFirst("uname");
        if (uname == null) {
            log.info("用户名为null,非法用户");
            exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
            return exchange.getResponse().setComplete();
        }
        // 放行
        return chain.filter(exchange);
    }

    /**
     * 相当于load-on-startup,定义过滤器链顺序
     * 过滤器加载的顺序越小,优先级别越高
     * @return
     */
    @Override
    public int getOrder() {
        return 0;
    }
}

8.3.2.2 测试

  • 成功

image.png

  • 失败

image.png

9. 网关解决全局跨域问题

Springboot1.0 二十二、跨域解决-CORS 2.2 配置类———全局配置

10. 解决绕过网关直连微服务问题

  1. 网络隔离:常用,只暴露网关端口、防火墙
  2. 网关增加全局Fliter:在Fliter增加Request Header
    1. 静态请求头:参考:8.2.1
    2. 动态请求头:参考:SpringCloud确保服务只能通过gateway转发访问,禁止直接调用接口访问