Spring Cloud第二季--服务网关Gateway

文章目录

  • 一、Gateway和Zuul的区别
  • 二、Gateway的核心概念
  • 三、小试牛刀
    • 3.1、代码测试
    • 3.2、关于Predicate
    • 3.3、关于Filter

一、Gateway和Zuul的区别

Spring Cloud Gateway是在Spring生态系统之上构建的API网关服务,基于Spring 5,Spring Boot 2和 Project Reactor等技术。 Gateway 使用的Webflux中的reactor-netty响应式编程组件,底层使用了Netty通讯框架。Spring Cloud Gateway能干嘛呢?
Spring Cloud第二季--服务网关Gateway_第1张图片

Gateway是原zuul1.x版的替代。

Spring Cloud Gateway 与 Zuul的区别:

Zuul 1.x,是一个基于阻塞 I/ O 的 API Gateway,不支持任何长连接,Zuul 用 Java 实现,而 JVM 本身会有第一次加载较慢的情况,使得Zuul 的性能相对较差。

Zuul 2.x理念更先进,想基于Netty非阻塞和支持长连接,但SpringCloud目前还没有整合。 Zuul 2.x的性能较 Zuul 1.x 有较大提升。在性能方面,根据官方提供的基准测试, Spring Cloud Gateway 的 RPS(每秒请求数)是Zuul 的 1. 6 倍。

Spring Cloud Gateway 建立 在 Spring Framework 5、 Project Reactor 和 Spring Boot 2 之上, 使用非阻塞 API。 支持 WebSocket, 并且与Spring紧密集成拥有更好的开发体验。

Spring Cloud第二季--服务网关Gateway_第2张图片

二、Gateway的核心概念

Route(路由)

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

Predicate(断言)

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

Filter(过滤)

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

如图Gateway官网所示的工作流程:
Spring Cloud第二季--服务网关Gateway_第3张图片

①、客户端向 Spring Cloud Gateway 发出请求。然后在 Gateway Handler Mapping 中找到与请求相匹配的路由,将其发送到 Gateway Web Handler。

②、Handler 通过指定的过滤器链来将请求发送到我们实际的服务执行业务逻辑,然后返回。

③、过滤器可能会在发送代理请求之前(“pre”)或之后(“post”)执行业务逻辑。

注: 在“pre”类型的过滤器可以做参数校验、权限校验、流量监控、日志输出、协议转换等,在“post”类型的过滤器中可以做响应内容、响应头的修改,日志的输出,流量监控等有着非常重要的作用。

三、小试牛刀

3.1、代码测试

使用SpringCloud Gateway测试之前,要开启Eureka Server,两个Eureka Client,请求调用过程如下:
Spring Cloud第二季--服务网关Gateway_第4张图片

新建model,添加pom依赖。GateWay属于SprinigCloud且有web依赖,在导入对应依赖时,要删除spring-boot-starter-web依赖

   <!--gateway-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-web</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!--eureka-client-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!--一般基础配置类-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

添加application.yml文件:

server:
  port: 9527

spring:
  application:
    name: cloud-gateway-service
  cloud:
    gateway:
      routes:
        - id: payment_route_one  #路由的ID,没有固定规则但要求唯一,建议配合服务名
          #uri: http://localhost:8001
          uri: lb://CLOUD-PAYMENT-SERVICE  #匹配后提供服务的路由地址
          filters:                         #过滤器,在路由成功后匹配执行
            - AddRequestParameter=X_Test,777
          predicates:                   # 断言,路径相匹配的进行路由
            - Path=/payment/get/**

        - id: payment_route_two
          uri: lb://CLOUD-PAYMENT-SERVICE    #uri的协议为lb,表示启用Gateway的负载均衡功能。
          predicates:
            - Path=/payment/show/**

        - id: payment_route_three
          uri: http://localhost:8001
          predicates:
            - Path=/payment/lb/**

      discovery:
        locator:
          enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由


eureka:
  instance:
    hostname: cloud-gateway-service
  client: #服务提供者provider注册进eureka服务列表内
    service-url:
      register-with-eureka: true
      fetch-registry: true
      defaultZone: http://eureka7001.com:7001/eureka




仔细分析一下配置中关于springcloud gateway的配置:

server:
  port: 9527

spring:
  application:
    name: cloud-gateway-service
  cloud:
    gateway:
      routes:
        - id: payment_route_one  #路由的ID,没有固定规则但要求唯一,建议配合服务名
          uri: lb://CLOUD-PAYMENT-SERVICE  #匹配后提供服务的路由地址
          filters:                         #过滤器,在路由成功后匹配执行
            - AddRequestParameter=X_Test,777
          predicates:                   # 断言,路径相匹配的进行路由
            - Path=/payment/get/**

routes 下面可以有多个路由配置,以id区分;每个路由有uri和predicates,表示当满足了predicates条件后,会成功路由到对应的uri;filters属性,增加了过滤器,表示在成功之后的路由中增加一个请求参数。

默认情况下Gateway会根据注册中心注册的服务列表,以注册中心上微服务名为路径创建动态路由进行转发,从而实现动态路由的功能uri的协议为lb,表示启用Gateway的负载均衡功能,lb://serviceName是spring cloud gateway在微服务中自动为我们创建的负载均衡uri。

启动类添加@EnableEurekaClient注解,启动Eureka Server和两个Eureka Client。

Spring Cloud第二季--服务网关Gateway_第5张图片
测试调用:

Spring Cloud第二季--服务网关Gateway_第6张图片
这个请求,从网关成功调用到8001。

Spring Cloud Gateway的路由配置,还支持以Bean的方式。

@Configuration
public class GateWayConfig {

    @Bean
    public RouteLocator getRouteLocator(RouteLocatorBuilder builder) {
        RouteLocatorBuilder.Builder routes = builder.routes();
        routes.route("payment_get_route", r -> r.path("/payment/two/get/**").uri("http://localhost:8002")).build();
        return routes.build();
    }

    @Bean
    public RouteLocator showRouteLocator(RouteLocatorBuilder builder) {
        RouteLocatorBuilder.Builder routes = builder.routes();
        routes.route("payment_show_route", r -> r.path("/payment/two/show/**").uri("http://localhost:8002")).build();
        return routes.build();
    }

}

Spring Cloud第二季--服务网关Gateway_第7张图片

3.2、关于Predicate

Spring Cloud Gateway 包括许多内置的Route Predicate工厂。所有这些Predicate都与HTTP请求的不同属性匹配。
Spring Cloud Gateway 创建 Route 对象时, 使用 RoutePredicateFactory 创建 Predicate 对象,Predicate 对象可以赋值给 Route。 Spring Cloud Gateway 包含许多内置的Route Predicate Factories。

Spring Cloud第二季--服务网关Gateway_第8张图片

3.3、关于Filter

路由过滤器可用于修改进入的HTTP请求和返回的HTTP响应,路由过滤器只能指定路由进行使用。

Spring Cloud Gateway 内置了多种路由过滤器,他们都由GatewayFilter的工厂类来产生。

Filter分为全局Filter和GatewayFilter ,其中GatewayFilter有近30种,常用的GatewayFilter在yml中针对单个route配置即可。
Spring Cloud第二季--服务网关Gateway_第9张图片GlobalFilter,可以自定义类实现 GlobalFilter,Ordered 接口,

Spring Cloud第二季--服务网关Gateway_第10张图片

/**
 * @Auther: songweichao
 * @Date: 2023-04-18 17:58
 * @Description:该全局过滤器,表示在所有的路由进来后,检查是否带某个参数,若携带,则通过,否则不通过。
 */

@Configuration
public class MyGateWayFilter implements GlobalFilter,Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain)
    {
        System.out.println("现在时间:"+new Date()+"\t 执行了自定义的全局过滤器: "+"MyGateWayFilter");

        String uname = exchange.getRequest().getQueryParams().getFirst("cookie");

        if (uname == null) {
            System.out.println("cookie为null,拒绝请求");
            exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
            return exchange.getResponse().setComplete();
        }
        return chain.filter(exchange);
    }

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

Spring Cloud第二季--服务网关Gateway_第11张图片
Spring Cloud第二季--服务网关Gateway_第12张图片

控制台打印

现在时间:Tue May 09 14:44:21 CST 2023	 执行了自定义的全局过滤器: MyGateWayFilter
现在时间:Tue May 09 14:44:47 CST 2023	 执行了自定义的全局过滤器: MyGateWayFilter
cookie为null,拒绝请求

这两部分可参考官网Spring Cloud Gateway,配合具体业务使用。

你可能感兴趣的:(Java填坑工程,Spring,Cloud,java学习笔记,spring,cloud,gateway,java,网关,SpringGateway)