【云原生&微服务>SCG网关篇三】Spring Cloud Gateway是什么、详细使用案例

一、前言

至此微服务网关系列文章已出:

  1. 【云原生&微服务>SCG网关篇一】为什么要有网关、生产环境如何选择网关
  2. 云原生&微服务>SCG网关篇二】生产上那些灰度发布方式

聊了以下问题:

  1. 为什么要有网关?网关的作用是什么?
  2. 网关的分类?
  3. 网关的技术选型?
  4. 使用网关时常用的灰度发布方式有哪些?

本文接着聊SpringCloud生态中的SpringCloudGateway是什么?并给出详细使用案例?

二、Spring Cloud Gateway

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

Spring Cloud Gateway 是Spring Cloud的第二代网关,用于替换Zuul;基于Netty、Reactor以及WebFlux构建。

1> 优点:

  • 性能强劲:Gateway基于netty和reactive模型构建,所以它的性能是Zuul的1.6倍左右。
  • 功能强大:内置了很多实用功能,比如转发、监控、限流等。
    • 注册到Nacos,自动检测nacos上其他的服务
    • 集成Ribbon、
    • 限流/容错(默认Hystrix,也可以用Sentinel)
  • 设计优雅、易扩展

2> 缺点:

  • 依赖Netty与WebFlux,不是Servlet编程模型,有一定的学习、适应成本。
  • 不能在Servlet容器下工作,只能打成jar包,不能构建成war包。
  • 不支持Spring Boot 1.X。

核心概念

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7XfYr7i9-1657682537099)(../picture/网关/gateway-链路.png)]

  • 路由(Route):路由是⽹关最基础的部分,路由信息由⼀个ID、⼀个目标URL、⼀组断⾔Predicate和⼀组Filter组成。如果断⾔路由为真,则说明请求的URL和配置匹配;也可以吧路由理解为一条请求转发规则。

    • ID:编号,路由的唯⼀标识;
    • URI:路由指向的⽬标 URI,即请求最终被转发的⽬的地。
    • Predicate:断言 / 谓语,作为路由的匹配条件。
    • Filter:过滤器,对请求和响应进⾏拦截,实现⾃定义的功能。
  • 断⾔/谓词(Predicate):Spring Cloud Gateway使用Predicate作为路由的匹配条件;Gateway 内置了多种 Predicate 的实现,提供了多种请求的匹配条件,⽐如说基于请求的 Path、Method 等等。

    即java.util.function.Predicate

  • 过滤器(Filter):过滤器Filter会对请求和响应进行拦截处理,实现自定义的功能;Gateway 内置了多种 Filter 的实现,提供了多种请求的处理逻辑,⽐如说限流、熔断等等。

此外,Spring Cloud Gateway启动时基于Netty Server 监听一个指定的端口(可以通过server.port属性自定义),Client的请求都会先打到Netty Server,然后再走到Predicates、Filters,最后走一层Netty proxy将请求转发到指定的微服务。

三、Gateway使用案例

整体项目目录包括两个Module,分别为:gateway-center、simple-service。
在这里插入图片描述
其中gateway-center作为路由网关、simple-service作为一个普通的微服务被整合到Gateway中。

0、最上层父项目spring-cloud-alibaba-center

spring-cloud-alibaba-center项目下只保留一个跟pom,用于做整体项目的maven依赖管理

1)pom.xml

<?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">
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.2</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>spring-cloud-alibaba-center</artifactId>
    <groupId>com.saint</groupId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-cloud-alibaba-center</name>
    <packaging>pom</packaging>

    <modules>
        <module>gateway-center</module>
        <module>simple-service</module>
    </modules>

    <properties>
        <java.version>1.8</java.version>
        <!-- 稳定老版本-->
        <!--        <spring-boot.version>2.3.7.RELEASE</spring-boot.version>-->
        <!--        <spring-cloud.version>Hoxton.SR9</spring-cloud.version>-->
        <!--        <spring-cloud-alibaba.version>2.2.6.RELEASE</spring-cloud-alibaba.version>-->

        <spring-boot.version>2.4.2</spring-boot.version>
        <spring-cloud.version>2020.0.1</spring-cloud.version>
        <spring-cloud-alibaba.version>2021.1</spring-cloud-alibaba.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-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!--整合spring cloud alibaba-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring-cloud-alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <!-- java编译插件 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

1、普通服务simple-service

simple-service项目整体代码结构目录如下:
在这里插入图片描述

其整体很简单、仅仅包含一个pom.xml文件、一个application.yml配置文件、一个启动类、一个Controller。

1、pom.xml

<?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">
    <parent>
        <artifactId>spring-cloud-alibaba-center</artifactId>
        <groupId>com.saint</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>simple-service</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <description>gateway-simple-service</description>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

</project>

2、application.yml

这里仅仅是设置服务的端口和程序名称。

server:
  port: 9001
spring:
  application:
    name: simple-service

3、启动类SimpleServiceApplication

package com.saint.simple;

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

/**
 * @author Saint
 */
@SpringBootApplication
public class SimpleServiceApplication {
    
    
    public static void main(String[] args) {
    
    
        SpringApplication.run(SimpleServiceApplication.class, args);
    }
}

就一个很普通的启动类。

4、启动simple-service

启动成功后,控制台输出如下:
在这里插入图片描述

2、搭建Gateway

Gateway-center整体代码结构目录如下:
在这里插入图片描述

其中包含一个pom.xml文件、一个application.yml配置文件、一个启动类;

1、pom.xml

<?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">
    <parent>
        <artifactId>spring-cloud-alibaba-center</artifactId>
        <groupId>com.saint</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>gateway-center</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <description>gateway-center</description>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

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

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>
</project>

2、application.yml

server:
  port: 9999
spring:
  application:
    name: gateway-center
  cloud:
    gateway:
      routes:
        - id: simple_service_route
          uri: http://127.0.0.1:9001
          predicates:
            # 路径匹配规则,向http://localhost:9999/gateway/simple-service/路径发送请求时,将会被转发到http://localhost:9001
            - Path=/gateway/simple-service/**
          filters:
            # StripPrefix参数表示在将请求发送到下游之前从请求中剥离的路径个数。
            # 如果设置StripPrefix=2,则当通过网关向/gateway/simple-service/hello发出请求时,对simple-service的请求将类似于/hello。
            - StripPrefix=2

application.yml配置文件中配置了一个Filter(StripPrefix),其表示在将请求发送到下游之前从请求路径(Predicate中的配置的Path)中剥离的路径个数;

以当前配置为例,Predicate中配置的Path为/gateway/simple-service/**,StripePrefix的值为2,当我们要通过gateway接收一个请求时,请求为:http://127.0.0.1:9999/gateway/simple-service/hello/sayHello,则转发到http://127.0.0.1:9001上的请求地址为:http://127.0.0.1:9001/hello/sayHello

3、启动类GatewayApplication

package com.saint.gateway;

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

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

4、启动gateway-center

启动成功后,控制台输出如下:
在这里插入图片描述
可以看到Gateway对外提供服务的Netty Server端口号为我们自定义的9999;

3、路由效果验证

上述步骤中,我们已经依次启动了simple-service、gateway-center;有两种方式可以访问到simple-service。

1> 直接访问simple-service:

在这里插入图片描述

2> 通过Gateway访问simple-service:

在这里插入图片描述

四、总结

目前一般SpringCloud生态都会选择使用Spring Cloud Gateway,当然也存在一些老项目至今仍在使用Zuul;Spring Cloud Gateway由WebFlux + Netty + Reactor组成,旨在为微服务架构提供⼀种简单且有效的API路由管理⽅式,并基于Filter的⽅式提供⽹关的基本功能,例如说安全认证、监控、限流。

另外:Spring Cloud Gateway是一个基于响应式的API业务⽹关。

后续博文我们继续聊Spring Cloud Gateway Predicate的使用

猜你喜欢

转载自blog.csdn.net/Saintmm/article/details/125756859