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 实战练习
- 新建 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}
- 新建 user-service 服务,十分简单,这里不在演示,注意需要注册到 Nacos。
user-service 服务的测试代码如下:
java
@Slf4j
@RestController
public class UserController {
@GetMapping("/query-user")
public String queryUser() {
return "张飞";
}
}
- 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
- 通过 Gateway 调用验证
我们通过 Gateway 的 8888 端口调用到了 user-service 服务的 queryUser 接口,并正常响应了,结果符合预期。
本篇关于 Spring Cloud Gateway 网关的初步认识和基本使用就介绍到这里,希望可以帮助到有需要的小伙伴。
如有不正确的地方请各位指出纠正。