Spring Cloud Gateway 网关的初步认识和基本使用

Gateway 简单介绍

Gateway 是 Spring Cloud 官方推出的第二代网关框架,用于取代 Zuul 网关,基于 Netty 和 WebFlux 由于没有使用 Sevlet 容器,故不能打成 war 包, Gateway 只支持 SpringBoot2.X 及以上版本。

Gateway 三大核心概念

  • 路由 Route : 可以理解为设置请求转发到指定服务器的过程,是构建网关的基本模块,由 ID、目标 URI、断言集合和过滤器集合组成,如果断言为 true 则匹配路由。
  • 断言 Predicate : 是 Java 8 的一个函数式接口 predicate,可以用于 lambda 表达式和方法引用,输入类型是:Spring Framework ServerWebExchange,允许开发人员使用断言来匹配来自 HTTP 请求中携带的内容,例如请求头 headers 和参数 paramers。
  • 过滤 Filter : 是使用特定工厂构建的 Spring Framework GatewayFilter 实例,GatewayFilter 通过使用过滤器,对请求进行拦截,在请求路由前后作出修改操作。

Gateway 主要功能

  • 鉴权。
  • 限流。
  • 熔断。
  • 日志监控。

Gateway 工作流程图

了解过 Gateway 的小伙伴,相信对下面这张图都不陌生,此图大概描述了请求的处理原理,以及各个组件大致的位置,各个组件的作用如下:

  • Gateway Client:发送请求到 Spring Cloud Gateway 的客户端。
  • Gateway Handler Mapping:处理请求的组件,负责将请求映射到相应的处理器,根据请求的路由规则,从而选择对应的过滤器链。
  • Gateway Web Handler:实际处理请求的组件,会依次执行过滤器链,对请求进行处理。
  • Gateway Filter:过滤器,是由一系列过滤器组成过滤器链,每个过滤器执行一些特定业务逻辑,过滤器之间用虚线分开是因为过滤器可能会在发送代理请求之前(pre)或之后(post)执行业务逻辑。
  • Proxied Service:被代理的服务,当执行完过滤器链之后会将请求转发到具体的目标服务。

Gateway 的核心逻辑是路由转发和执行过滤器链。

GatewayFilterFactory Gateway过滤器工厂

Spring提供了31种不同的路由过滤器工厂,具体如下:

名称 作用
AddRequestHeader 给当前请求添加一个请求头
AddRequestParameter 为原始请求添加请求参数
AddResponseHeader 给响应结果中添加一个响应头
DedupeResponseHeader 去掉重复请求头
Spring Cloud CircuitBreaker 断路器
FallbackHeaders 添加熔断后的异常信息到请求头
MapRequestHeader 将上游请求头的值赋值到下游请求头
PrefixPath 匹配的路由添加前缀
Preserve Host Header 保留原请求头
RequestRate Limiter 限制请求的流量
RedirectTo 重定向
RemoveRequestHeader 移除请求中的一个请求头
RemoveRequestParameter 移除请求参数
RewritePath 重写路径
RewriteLocationResponseHeader 重写响应头中 Location 的值
Rewrite ResponseHeader 重写响应头
SaveSession 向下游转发请求前前置执行 WebSession save 的操作
SecureHeaders 禁用默认值
SetRequestHeader 重置请求头
SetResponseHeader 修改响应头
SetStatus 修改响应的状态码
StripPrefix 对指定数量的路径前缀进行去除
Retry 重试
RequestSize 请求大小大于限制时,限制请求到达下游服务
SetRequestHostHeader 重置请求头值
ModifyRequestBody 修改请求体内容
ModifyResponse Body 修改响应体内容
Relay 将OAuth2访问令牌向下游转发到它所代理的服务
CacheRequestBody 在请求正文发送到下游之前缓存请求正文并从exchagne属性获取正文

Gateway 实战练习

  1. 新建 cloud-gateway 服务,引入 gateway 相关依赖,并将 cloud-gateway 注册到 Nacos,这里不在演示创建服务的过程,只展示引入的相关依赖。

pom.xml 文件如下:

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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.5</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.user.service</groupId>
    <artifactId>user-service</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>user-service</name>
    <description>user-service</description>

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!--引入 Nacos 支持-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            <version>2021.1</version>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-netflix-ribbon</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
            <version>2021.1</version>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-netflix-ribbon</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <!--引入 sentinel 支持-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
            <version>2021.1</version>
        </dependency>

        <!--引入 OpenFeign 支持-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
            <version>3.0.1</version>
        </dependency>

        <!--引入 LoadBalancer 支持-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
            <version>3.0.1</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bootstrap</artifactId>
            <version>3.0.0</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-commons</artifactId>
            <version>3.0.1</version>
            <scope>compile</scope>
        </dependency>

        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-nacos</artifactId>
            <version>1.8.0</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

could-gateway 服务 properties 文件如下:

java 复制代码
#服务名
spring.application.name=cloud-gateway
#端口
server.port=8888
#开启从注册中心动态创建路由的功能,利用微服务名称进行路由
spring.cloud.gateway.discovery.locator.enabled=true
#服务路由名小写
spring.cloud.gateway.discovery.locator.lower-case-service-id=true
#路由唯一标志
spring.cloud.gateway.routes[0].id = user-service
#路由指向目标 URL 服务名 客户端请求最终被转发到的微服务 推荐使用服务名称
spring.cloud.gateway.routes[0].uri = lb://user-service
#断言 以 /api/user 开头的请求都转发到 user-service 服务
spring.cloud.gateway.routes[0].predicates[0] = Path=/api/user/**
#过滤器 过滤掉 url 里的 /api/user 例如 http://ip:port/api/user/query-order 过滤后的地址是  http://ip:port/query-order
#如果不使用这个过滤器 直接在目标微服务的所有 api 路径前加上 /api/user  也是一样的
spring.cloud.gateway.routes[0].filters[0] = RewritePath=/api/user/(?<segment>.*), /$\{segment}
  1. 新建 user-service 服务,十分简单,这里不在演示,注意需要注册到 Nacos。

user-service 服务的测试代码如下:

java 复制代码
@Slf4j
@RestController
public class UserController {

    @GetMapping("/query-user")
    public String queryUser() {
        return "张飞";
    }

}
  1. cloud-gateway 和 user-service 注册在同一个 Nacos 的同一个 Namespace 的同一个 Group 上,如下图所示:

需要注意的是 cloud-gateway 和 user-service 在 Nacos 上的 Namespace、Group 必须保证一样,否则会无法调用,Gateway 会有如下日志:

java 复制代码
 2024-08-09 20:21:36.251  WARN 22008 --- [oundedElastic-6] o.s.c.l.core.RoundRobinLoadBalancer      : No servers available for service: user-service
  1. 通过 Gateway 调用验证

我们通过 Gateway 的 8888 端口调用到了 user-service 服务的 queryUser 接口,并正常响应了,结果符合预期。

本篇关于 Spring Cloud Gateway 网关的初步认识和基本使用就介绍到这里,希望可以帮助到有需要的小伙伴。

如有不正确的地方请各位指出纠正。

相关推荐
QQ_115432031几秒前
基于Java+SpringBoot+Mysql在线简单拍卖竞价拍卖竞拍系统功能设计与实现四
java·spring boot·mysql·毕业设计·毕业源码·竞拍系统·竞拍平台
fa_lsyk6 分钟前
Spring:AOP面向切面案例讲解AOP核心概念
java·后端·spring
陈奕迅本讯7 分钟前
人力资源项目学习
java·学习
2401_878467329 分钟前
大连环保公益管理系统|Java|SSM|Vue| 前后端分离
java·开发语言·学习·tomcat·maven
Genius Kim13 分钟前
JWT加解密应用方案设计与实现
java·开发语言
尘浮生29 分钟前
Java项目实战II基于SpringBoot的客户关系管理系统(开发文档+数据库+源码)
java·开发语言·数据库·spring boot·后端·微信小程序·小程序
2401_8576100331 分钟前
企业OA系统:Spring Boot技术实现与管理
java·spring boot·后端
飞滕人生TYF33 分钟前
java 集合 菱形内定义封装类 而非基本数据类型 原因解释 详解
java
繁依Fanyi36 分钟前
在 Spring Boot 中实现多种方式登录(用户名、手机号、邮箱等)的不正经指南
java·spring boot·后端
夕阳产业——JAVA,入坑=失业38 分钟前
泛型擦除是什么?
java·开发语言