SpringCloud H版 GateWay 网关路由讲解

Posted 小毕超

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringCloud H版 GateWay 网关路由讲解相关的知识,希望对你有一定的参考价值。

一、GateWay 网关

在上篇文章中我们介绍了,hystrix 的使用,本篇文章我们继续探索,Spring cloud GateWay网关:

上篇文章地址:https://blog.csdn.net/qq_43692950/article/details/121998205

Gateway是在Spring生态系统之上构建的API网关服务,基于Spring 5,Spring Boot 2和 Project Reactor等技术。Gateway旨在提供一种简单而有效的方式来对API进行路由,以及提供一些强大的过滤器功能, 例如:熔断、限流、重试等。

Gateway 是 Spring Cloud 的一个全新项目,基于 Spring 5.0+Spring Boot 2.0 和 Project Reactor 等技术开发的网关,它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式。

Gateway 作为 Spring Cloud 生态系统中的网关,目标是替代 Zuul,在Spring Cloud 2.0以上版本中,没有对新版本的Zuul 2.0以上最新高性能版本进行集成,仍然还是使用的Zuul 1.x非Reactor模式的老版本。而为了提升网关的性能,SpringCloud Gateway是基于WebFlux框架实现的,而WebFlux框架底层则使用了高性能的Reactor模式通信框架Netty。

Spring Cloud Gateway的目标提供统一的路由方式且基于 Filter 链的方式提供了网关基本的功能,例如:安全,监控/指标,和限流。

为什么选择GateWay呢?

一方面因为Zuul1.0已经进入了维护阶段,而且Gateway是SpringCloud团队研发的,是亲儿子产品,值得信赖。而且很多功能Zuul都没有用起来也非常的简单便捷。

Gateway是基于异步非阻塞模型上进行开发的,性能方面不需要担心。虽然Netflix早就发布了最新的 Zuul 2.x,但 Spring Cloud 貌似没有整合计划。而且Netflix相关组件都宣布进入维护期;不知前景如何?

多方面综合考虑Gateway是很理想的网关选择。

Spring Cloud Gateway 具有如下特性:

  • 基于Spring Framework 5, Project Reactor 和 Spring Boot 2.0 进行构建;
  • 动态路由:能够匹配任何请求属性;
  • 可以对路由指定 Predicate(断言)和 Filter(过滤器);
  • 集成Hystrix的断路器功能;
  • 集成 Spring Cloud 服务发现功能;
  • 易于编写的 Predicate(断言)和 Filter(过滤器);
  • 请求限流功能;
  • 支持路径重写。

GateWay 对比 Zuul

在SpringCloud Finchley 正式版之前,Spring Cloud 推荐的网关是 Netflix 提供的Zuul,但Zuul在现在数据量大的场景有些不适合,比如

  • Zuul 1.x,是一个基于阻塞 I/ O 的 API Gateway

  • Zuul 1.x 基于Servlet 2. 5使用阻塞架构它不支持任何长连接(如 WebSocket) Zuul 的设计模式和nginx较像,每次 I/ O 操作都是从工作线程中选择一个执行,请求线程被阻塞到工作线程完成,但是差别是Nginx 用C++ 实现,Zuul 用 Java 实现,而 JVM 本身会有第一次加载较慢的情况,使得Zuul 的性能相对较差。

Netflix 官方早就称开发zuul2,并且适配现在大数据的是时代,但随着Spring Cloud Gateway的出现及使用的普遍性,zuul2也不怎么被人提起。下面是两者的优点介绍:

  • 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。

  • Spring Cloud Gateway 还 支持 WebSocket, 并且与Spring紧密集成拥有更好的开发体验

二、准备服务提供者

由于我们还没讲解到nacos,本篇文章我们还是使用注册中心eureka,还是接着前几篇的搭建的架构继续,启动注册中心,还有服务提供者:

由于今天主要讲解GateWay,大家也可以改写为自己的接口。
以下是提供者所提供的接口。

@RestController
public class ProviderController 

    @Value("$server.port")
    private String port;

    @GetMapping("/getData")
    public ResponseTemplate providerData() 

        return ResSuccessTemplate.builder().data("come from : " + port).build();
    

    @GetMapping("/provider/getData")
    public ResponseTemplate providerData2() 

        return ResSuccessTemplate.builder().data("providerData2 come from : " + port).build();
    

    @GetMapping("/getTimeData")
    public ResponseTemplate getTimeData() throws InterruptedException 
        TimeUnit.SECONDS.sleep(5);
        return ResSuccessTemplate.builder().data("come from : " + port).build();
    

三、搭建GateWay 网关

本篇还是采用Spring cloud H版 S9 版本进行演示:

<properties>
    <java.version>1.8</java.version>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <spring-boot.version>2.3.7.RELEASE</spring-boot.version>
    <spring-cloud.version>Hoxton.SR9</spring-cloud.version>
    <model.version>0.0.1-SNAPSHOT</model.version>
</properties>
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>$spring-boot.version</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>

        <!--spring cloud Hoxton.SR1-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>$spring-cloud.version</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>

    </dependencies>
</dependencyManagement>

新建SpringBoot项目,在pom中引入依赖:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

注意这里不要引入spring-boot-starter-web这个包,Spring cloud gateway 使用的webflux,引入web包会报错,提示你不要引用。

主启动类:

@SpringBootApplication
@EnableEurekaClient
public class GateWayApplication 
    public static void main(String[] args) 
        SpringApplication.run(GateWayApplication.class, args);
    

修改配制文件:

server:
  port: 80

eureka:
  client:
    register-with-eureka: true
    fetchRegistry: true
    service-url:
      defaultZone: http://eureka1:8010/eureka,http://eureka2:8011/eureka
    
spring:
  application:
    name: gateway
  cloud:
    gateway:
      httpclient:
        connect-timeout: 2000
        response-timeout: 10s
      routes:
        - id: provider1
          uri: http://127.0.0.1:8091
          order: 0
          predicates:
            - Path=/provider1/**
          filters:
            - StripPrefix=1 # 去除请求地址中的前缀

上面配制文件eureka的配制就不多说了,主要看下面 gateway的配制,- id 表示声明一个路由规则,保证唯一即可,uri 表示代理后的地址,order 排序,如果有多个规则们可以使用这个指定顺序,predicates 这个是本篇文章的重点,表示断言,也就是路由规则,上面配制的规则就是请求地址中以 /provider1 开头的地址会转发到 uri 中,最后是指定了一个 过滤器,这个 StripPrefix=1 表示去除请求地址中的前缀,如果不加这个过滤器,转发的地址就是 http://127.0.0.1:8091/provider1/

路由规则一方面可以在配制中声明出来,也可以在程序中声明出来,比如:

@Configuration
public class GateWayConfig

    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder)
    
        RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();
        
        routes.route("provider1",
                r -> r.path("/provider1")
                        .uri("http://127.0.0.1:8091")).build();
                        
        return routes.build();
    

现在大多还是以配制文件中配制为主,本篇文章也已配制文件为主讲解。

下面浏览器请求:http://127.0.0.1/provider1/getData

到此就已经有网关转发的功能了,下面学习下,更多转发方面的技能。

四、predicates 断言

上面说到,本篇的主要内容是predicates 断言,基本所有的转发规则都是配制在predicates 中的。

下面是 predicates 所支持的功能。

官方文档: https://docs.spring.io/spring-cloud-gateway/docs/3.0.5-SNAPSHOT/reference/html/

1. 转发注册中心的服务

配制修改:

- id: provider
  uri: lb://provider/
  predicates:
    - Path=/provider/**,/lbprovider/**  #或者
  filters:
    - StripPrefix=1 # 去除请求地址中的前缀

浏览器请求:http://127.0.0.1/lbprovider/getData


可以看出如果多个,默认采用轮训的效果。

2. 过滤 请求头 Header

现在基本都是前后端分离,那用户的状态使用多的应该就是token了,而token我们一般是放在请求头上,因此我们可以过滤,请求头中没有token,不允许访问:

- id: provider1
  uri: http://127.0.0.1:8091/provider
  order: 0
  predicates:
    - Header=token
    - Path=/provider1/**
  filters:
    - StripPrefix=1 # 去除请求地址中的前缀

使用postman访问:http://127.0.0.1/provider1/getData


在header中加入token参数

3. 过滤 请求参数

限制必须携带某些参数:

- id: provider1
  uri: http://127.0.0.1:8091/provider
  order: 0
  predicates:
    - Path=/provider1/**
    - Query=user
  filters:
    - StripPrefix=1 # 去除请求地址中的前缀

4. 过滤 请求 ip

- id: provider1
  uri: http://127.0.0.1:8091/provider
  order: 0
  predicates:
    - Path=/provider1/**
    - RemoteAddr=192.168.1.7
  filters:
    - StripPrefix=1 # 去除请求地址中的前缀

必须使用 http://192.168.1.7/provider1/getData?user=123 才可以访问:

4. 过滤 请求 Host

- id: provider1
  uri: http://127.0.0.1:8091/provider
  order: 0
  predicates:
    - Path=/provider1/**
    - Host=eureka1
  filters:
    - StripPrefix=1 # 去除请求地址中的前缀

必须使用:http://eureka1/provider1/getData?user=123 才能访问

5. 过滤 请求方法

- id: provider1
  uri: http://127.0.0.1:8091/provider
  order: 0
  predicates:
    - Path=/provider1/**
    - Method=GET
  filters:
    - StripPrefix=1 # 去除请求地址中的前缀

限制只有Get请求会转发

6. 过滤 cookie

- id: provider1
  uri: http://127.0.0.1:8091/provider
  order: 0
  predicates:
    - Path=/provider1/**
    - Cookie=sessionId
  filters:
    - StripPrefix=1 # 去除请求地址中的前缀

限制只有Cookie中带有 sessionId 参数的可以转发。

7. 请求添加前缀

- id: provider1
  uri: http://127.0.0.1:8091
  order: 0
  predicates:
    - Path=/provider1/**
  filters:
    - StripPrefix=1 # 去除请求地址中的前缀
    - PrefixPath=/provider #添加前缀



喜欢的小伙伴可以关注我的个人微信公众号,获取更多学习资料!

以上是关于SpringCloud H版 GateWay 网关路由讲解的主要内容,如果未能解决你的问题,请参考以下文章

SpringCloud H版 GateWay 过滤器讲解 及 使用Guava 统一限流处理。

SpringCloud(Greenwich版)新一代API网关Gateway

3W字吃透:微服务网关SpringCloud gateway底层原理和实操

springcloud-gateway 网关异常处理

SpringCloud --- 服务网关 (Gateway)

SpringCloud --- 服务网关 (Gateway)