微服务SpringCloud(Gateway网关)整合十七

上一篇中,我们讲了这个这个zuul组件,今天我们讲一个新的网关组件Spring Cloud Gateway。为什么要讲这组件呢?因为这个SpringCloud Gateway 作为 Spring Cloud 生态系统中的网关,目标是替代 Zuul,在Spring Cloud 2.0以上版本中,没有对新版本的Zuul 2.0以上最新高性能版本进行集成,仍然还是使用的Zuul 1.x非Reactor模式的老版本。而为了提升网关的性能,SpringCloud Gateway是基于WebFlux框架实现的,而WebFlux框架底层则使用了高性能的Reactor模式通信框架Netty。说明了Gateway的性能是要比zuul要好的,而且zuul更新太慢了。所以springcloud是推荐我们在项目中使用Gateway网关代替zuul的。

SpringCloud Gateway 官网地址:
https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/html/

SpringCloud Gateway是什么?

SpringCloud全家桶中有个很重要的组件就是网关,在1.x版本中都是采用的Zuul网关;
但在2.x版本中,zuul的升级一直在延期,所以SpringCloud最后自己研发了一个网关替代Zuul,
那就是SpringCloud Gateway一句话:gateway是原zuul1.x版的替代组件。

SpringCloud Gateway可以做什么?
  • 反向代理
  • 鉴权
  • 流量监控
  • 日志监控
SpringCloud Gateway 与 Zuul的区别是是什么?

1、Zuul 1.x,是一个基于阻塞 I/ O 的 API Gateway
2、Zuul 1.x 基于Servlet 2. 5使用阻塞架构它不支持任何长连接(如 WebSocket) 。Zuul 的设计模式和Nginx较像,每次 I/ O 操作都是从工作线程中选择一个执行,请求线程被阻塞到工作线程完成,但是差别是Nginx 用C++ 实现,Zuul 用 Java 实现,而 JVM 本身会有第一次加载较慢的情况,使得Zuul 的性能相对较差。
3、Zuul 2.x理念更先进,想基于Netty非阻塞和支持长连接,但SpringCloud目前还没有整合。 Zuul 2.x的性能较 Zuul 1.x 有较大提升。在性能方面,根据官方提供的基准测试, Spring Cloud Gateway 的 RPS(每秒请求数)是Zuul 的 1. 6 倍。
4、Spring Cloud Gateway 建立 在 Spring Framework 5、 Project Reactor 和 Spring Boot 2 之上, 使用非阻塞 API。

SpringCloud 三个核心概念

1、Route(路由)
路由是构建网关的基本模块,它由ID,目标URI,一系列的断言和过滤器组成,如果断言为true则匹配该路由。
2、Predicate(断言)
请求与断言相匹配则进行路由
3、Filter(过滤)
Spring框架中GatewayFilter的实例,使用过滤器,可以在请求被路由前或者之后对请求进行修改。

在我们的web请求中,可以通过一些匹配条件,定位到真正的服务节点。并在这个转发过程的前后,进行一些精细化控制。predicate就是我们的匹配条件;而filter,就可以理解为一个无所不能的拦截器。有了这两个元素,再加上目标uri,就可以实现一个具体的路由了

GateWay 官网的流程图

在这里插入图片描述
客户端向 Spring Cloud Gateway 发出请求。然后在 Gateway Handler Mapping 中找到与请求相匹配的路由,将其发送到 Gateway Web Handler。Handler 再通过指定的过滤器链来将请求发送到我们实际的服务执行业务逻辑,然后返回。过滤器之间用虚线分开是因为过滤器可能会在发送代理请求之(“pre”)或之后(“post”)执行业务逻辑。Filter在“pre”类型的过滤器可以做参数校验、权限校验、流量监控、日志输出、协议转换等,在“post”类型的过滤器中可以做响应内容、响应头的修改,日志的输出,流量监控等有着非常重要的作用。

SpringCloud GateWay 项目整合

新建Module pcloud-gateway-gateway8888
在这里插入图片描述
在这里插入图片描述
修改pom文件:

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <parent>
    <artifactId>pcloud</artifactId>
    <groupId>com.younger.springcloud</groupId>
    <version>1.0-SNAPSHOT</version>
  </parent>

  <groupId>com.younger.springcloud</groupId>
  <artifactId>pcloud-gateway-gateway8888</artifactId>
  <version>1.0-SNAPSHOT</version>

  <name>pcloud-gateway-gateway8888</name>

  <dependencies>
    <!--gateway-->
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-gateway</artifactId>
    </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>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
    </dependency>
  </dependencies>

</project>

新增 application.yml文件

server:
  port: 8888

spring:
  application:
    name: pcloud-gateway

eureka:
  instance:
  client: #服务提供者provider注册进eureka服务列表内
    service-url:
      register-with-eureka: true
      fetch-registry: true
      defaultZone: http://eureka6001:6001/eureka/

编写启动类: GateWayMain8888

package com.younger.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

@SpringBootApplication
@EnableEurekaClient
public class GateWayMain8888 {

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

接下来我们开始编写我们的网关配置了:
在这里插入图片描述

server:
  port: 8888

spring:
  application:
    name: pcloud-gateway
  cloud:
    gateway:
      routes:
        - id: pcloud-user-service # 路由的ID,没有固定的规则但是要求需要统一,可以使用我们的服务名
          uri: http://localhost:8001 #匹配后提供服务的路由地址
          predicates:
            - Path=/user/** # 断言 路径相匹配进行地址路由


eureka:
  instance:
  client: #服务提供者provider注册进eureka服务列表内
    service-url:
      register-with-eureka: true
      fetch-registry: true
      defaultZone: http://eureka6001:6001/eureka/

在这里插入图片描述
在这里插入图片描述
这两个地址是想对应的。

我们现在测试一下:
在这里插入图片描述
测试地址:http://localhost:8888/user/1
在这里插入图片描述
我们不仅可以通过yml文件配置,还可以通过Java 方式配置路径:
在这里插入图片描述
编写GateWayConfig类:

package com.younger.springcloud.config;

import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class GateWayConfig {


    /**
     *  1、配置id 为 path_routh
     *  2、访问http:loclhost:8888/cnds 会跳转到地址https://www.csdn.net/
     * @param builder
     * @return
     */

    @Bean
    public RouteLocator routeLocator (RouteLocatorBuilder builder) {
        RouteLocatorBuilder.Builder routes = builder.routes();
        routes.route("path_routh",r->r.path("/cnds").uri("https://www.csdn.net/")).build();
        return routes.build();
    }
}

启动项目:
测试地址: http:loclhost:8888/cnds
在这里插入图片描述
我们在上面的案例中的配置文件写死了访问地址 如下图:
在这里插入图片描述
如果我们有多台服务要怎么办呢?SpringCloud Gateway 也提供负载均衡访问服务,我们来修改下我们的配置文件:
在这里插入图片描述
我们把8001、8002 启动起来:
在这里插入图片描述
测试地址:http://localhost:8888/user/1
在这里插入图片描述
可以看到 8001、8002 在来回切换。

SpringCloud Gateway 断言(predicates)

SpringCloud Gateway的路由,我们大概知道是怎么回事了,那这个predicates断言又是啥呢?我们可以去SpringCloud的官网看下:
在这里插入图片描述
可以看到 SpringCloud Gateway 提供了很多不同的断言方式,我们刚才使用的Path 就是其中的一种,我们看下其他的断言:
1、The After Route Predicate Factory 意思就是这个地址只能在这个日期之后才可以访问
配置文件:
在这里插入图片描述

- After=2022-03-11T18:56:03.685+08:00[Asia/Shanghai]

如果在这个时间点前访问就会出现404
在这里插入图片描述
2、 The Before Route Predicate Factory 意思就是这个地址只能在这个日期之前才可以访问
在这里插入图片描述

- Before=2022-03-10T17:10:03.685+08:00[Asia/Shanghai]

3、 The Between Route Predicate Factory 两个时间节点之间
在这里插入图片描述
其他的断言配置可以参考 https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/html/#the-cookie-route-predicate-factory 官网提供的案例,自己测试一下。
这个是它的所有的配置:
在这里插入图片描述

SpringCloud Gateway 过滤器(filter)

路由过滤器可用于修改进入的HTTP请求和返回的HTTP响应,路由过滤器只能指定路由进行使用。
官网中的过滤器有很多
在这里插入图片描述

我们根据官网的提供的案例进行配置:
在这里插入图片描述

- AddRequestParameter=X-Request-Id,2048 #过滤器工厂会在匹配的请求头加上一对请求头,名称为X-Request-Id值为2048

SpringCloud Gateway 的全局过滤器:
在这里插入图片描述
我们自定义定义一个全局过滤器 MyLogGateWayFilter 类:

package com.younger.springcloud.filter;

import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

@Component
public class MyLogGateWayFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        System.out.println("执行全局的过滤器......");
        String username = exchange.getRequest().getQueryParams().getFirst("username");
        if (username == null) {
             System.out.println("username不能为空");
            exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
            return exchange.getResponse().setComplete();
        }
        return chain.filter(exchange);
    }

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

重新启动项目测试:
在这里插入图片描述
测试地址: http://localhost:8888/user/lb
在这里插入图片描述
在这里插入图片描述

测试地址: http://localhost:8888/user/lb?username=‘younger’
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

youngerone123

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值