为什么需要Gateway

通用功能的抽取
前端在调用后端的服务时,往往都需要先通过一些通用的功能,比如跨域,权限校验,限流等。

如果没有Gateway,那么这些功能都需要在每个服务里单独实现一遍,那么就会有很多的重复代码。

地址的维护
如果没有Gateway,每一个微服务都需要在前端维护一个调用地址,如果有几百个微服务就有几百个地址,那么前端会非常痛苦。

有了Gateway就统一交给Gateway来管理,前端直接请求网关即可。

其他功能
image.png

什么是Gateway

Spring官方开发的,基于webflux + Netty + Reactor 实现的响应式API网关,不能运行在传统的servlet中,也不能构建成war包。

快速开始

  1. 在父项目中创建子项目gateway
  2. 添加依赖

    1. <dependencies>
    2. <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-gateway -->
    3. <dependency>
    4. <groupId>org.springframework.cloud</groupId>
    5. <artifactId>spring-cloud-starter-gateway</artifactId>
    6. </dependency>
    7. </dependencies>
  3. 添加启动类 ```java package com.lang;

import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication public class GatewayApplication { public static void main(String[] args) { SpringApplication.run(GatewayApplication.class, args); } }


4. 添加配置文件application.yml
```java
server:
  port: 8088
Spring:
  application:
    name: api-gateway
  cloud:
  #gateway的配置
    gateway:
      #路由规则
      routes:
        - id: order_route #路由的唯一标识
          uri: http://localhost:8010  #需要转发的地址
          #断言规则 用于路由规则的匹配
          predicates:
            - Path=/order-serv/**
              # http://localhost:8088/order-serv/order/add
              # 路由到http://localhost:8010/order-serv/order/add
          filters:
            - StripPrefix=1
              # 去除掉第一层路径order-serv,保证转发后的路径是正确的
              # 即http://localhost:8010/order/add
  1. 启动微服务并访问http://localhost:8088/order-serv/order/add

image.png

Gateway整合Nacos

在上面的快速开始中,仍然手动维护了调用的地址,整合了Nacos后就不需要手动写死调用地址了。

  1. 引入依赖

    <dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
    
  2. 修改配置文件 ```xml server: port: 8088 Spring: application: name: api-gateway cloud:

    gateway的配置

    gateway:

    路由规则

    routes:

     - id: order_route #路由的唯一标识
       uri: lb://order-service  #需要转发的地址 lb就是loadbalance, 即使用nacos中的负载均衡策略
       #断言规则 用于路由规则的匹配
       predicates:
         - Path=/order-serv/**
           # http://localhost:8088/order-serv/order/add
           # 路由到http://localhost:8010/order-serv/order/add
       filters:
         - StripPrefix=1
           # 去除掉第一层路径order-serv,保证转发后的路径是正确的
           # 即http://localhost:8010/order/add
    

    nacos: server-addr: 127.0.0.1:8848 discovery:

     username: nacos
     password: nacos
     namespace: public
    
主要修改了:

- 添加了nacos的配置
- 将uri改成了服务名`lb://order-service`

3. 重启项目并访问原来的链接,发现可以正常访问。

于是,我们就完成了网关和Nacos的集成。

<a name="gKdxr"></a>
# 断言(predicates)详解
断言就是根据一定的规则,来确定要不要进行路由的转发,例如在上面的例子中:
```xml
predicates:
- Path=/order-serv/**

就表示,路径必须要符合xxxxx/order-serv/xxxx才会进行转发。

不同类型的断言方式称之为不同的断言工厂。包括内置的断言工厂和自定义的断言工厂。

基于时间的断言工厂

  • 时间之前BeforeRoutePredicateFactory: 接收一个日期参数,判断请求日期是否早于指定日期
  • 时间之间BetweenRoutePredicateFactory: 接收两个日期参数,判断请求日期是否在指定时间段内
  • 时间之后AfterRoutePredicateFactory: 接收一个日期参数,判断请求日期是否晚于指定日期

基于远程地址的断言工厂

RemoteAddrRoutePredicateFactory:接收一个IP地址段,判断请求主机地址是否在地址段中

基于Cookie的断言工厂

CookieRoutePredicateFactory:接收两个参数,cookie 名字和一个正则表达式。 判断请求
cookie是否具有给定名称且值与正则表达式匹配。

‐Cookie=chocolate, ch.

基于Method请求方法的断言工厂

MethodRoutePredicateFactory:接收一个参数,判断请求类型是否跟指定的类型匹配。

‐Method=GET

等等等等,具体可以看文档。

过滤器(Filter)详解

也有很多内置的过滤器。即在转发的时候,对请求进行一些操作,例如去掉第一级,添加头部信息,重定向等等等等。

全局过滤器

全局过滤器对所有路由生效,而且一旦定义了,不需要额外进行配置,即可投入使用。

image.png

自定义全局过滤器:

  1. 继承GlobalFilter;
  2. 重写方法;
  3. 添加Comonent注解;
    @Component
    public class LogGlobalFilter implements GlobalFilter {
     Logger logger = LoggerFactory.getLogger(this.getClass());
     @Override
     public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
         logger.info(exchange.getRequest().getPath().value());
         return chain.filter(exchange);
     }
    }
    
    访问时可以看到
    2021-10-08 20:16:21.395  INFO 27768 --- [ctor-http-nio-2] com.lang.filters.LogGlobalFilter         : /order/add