一、前言
Spring Cloud 原先整合 Zuul 作为网关组件,Zuul 由 Netflix 公司提供的,现在已经不维护了。后面 Netflix 公司又出来了一个 Zuul2.0 网关,但由于一直没有发布稳定版本,所以 Spring Cloud 等不及了就自己推出一个网关,已经不打算整合 zuul2.0 了。
Spring Cloud Gateway 是 Spring 公司基于 Spring 5.0, Spring Boot 2.0 和 Project Reactor 等技术开发的网关,它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式。它的目标是替代 Netflix Zuul,其不仅提供统一的路由方式,并且基于 Filter 链的方式提供了网关基本的功能,例如:安全,监控和限流。
二、Gateway 介绍
2.1 核心概念
- 路由:网关的基本构建组成,表示一个具体的路由信息载体。它由 ID,目标 URI,谓词集合和过滤器集合定义
- 谓词/断言:Java 8 函数谓词,输入类型是 Spring Framework ServerWebExchange,可以匹配 HTTP 请求中的所有内容,例如请求头或参数
- 过滤器:使用特定工厂构造的 Spring Framework GatewayFilter 实例,可以在发送给下游请求之前或之后修改请求和响应
2.2 执行流程
执行流程大体如下:
- Gateway Client 向 Gateway Server 发送请求
- 请求首先会被 HttpWebHandlerAdapter 进行提取组装成网关上下文
- 然后网关的上下文会传递到 DispatcherHandler,它负责将请求分发给 RoutePredicateHandlerMapping
- RoutePredicateHandlerMapping 负责路由查找,并根据路由断言判断路由是否可用
- 如果过断言成功,由 FilteringWebHandler 创建过滤器链并调用
- 请求会一次经过 PreFilter -> 微服务 -> PostFilter 的方法,最终返回响应
三、环境搭建
为了更好的理解上边提到核心概念,我们现用简单的实战案例演示。
项目名称 | 端口 | 描述 |
---|---|---|
gateway-test | - | pom 项目,父工厂 |
user-service | 9001 | 用户微服务,服务注册到 nacos |
gateway-service | 9090 | 网关服务,服务注册到 nacos |
注意:搭建项目启动前,必须先开启 Nacos 服务。
3.1 搭建 gateway-test 项目
该工程为 pom 项目,只需要添加如下依赖:
<packaging>pom</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
</parent>
<dependencyManagement>
<dependencies>
<!-- spring cloud 依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- spring cloud alibaba 依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.2.1.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
3.2 搭建 user-service 项目
该项目为用户微服务,模拟提供用户相关接口。
1. 添加依赖:
<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>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
2. 配置文件(application.yml):
server:
port: 9001
spring:
application:
name: user-service
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
username: nacos
password: nacos
3.业务类:
@Data
@AllArgsConstructor
public class User {
private Integer id;
private String name;
}
@RestController
@RequestMapping("/user")
public class UserController {
private static Map<Integer, User> userMap;
static {
userMap = new HashMap<>();
userMap.put(1, new User(1, "张三"));
userMap.put(2, new User(2, "李四"));
userMap.put(3, new User(3, "王五"));
}
@RequestMapping("/findById/{id}")
public User findById(@PathVariable("id") Integer id) {
// 为了测试方便,用此方式模拟用户查询
return userMap.get(id);
}
}
4.启动类:
@SpringBootApplication
@EnableDiscoveryClient
public class UserApplication {
public static void main(String[] args) {
SpringApplication.run(UserApplication.class, args);
}
}
启动用户微服务,浏览器输入:h t t p:// localhost:9001/user/findById/1,结果如下图:
用户微服务正常。
3.3 搭建 gateway-service 项目
该服务提供网关功能,核心就是配置路由规则。
1.添加依赖:
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
</dependencies>
2.配置文件(application.yml):
server:
port: 9090
spring:
application:
name: gateway-service
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
username: nacos
password: nacos
gateway:
discovery:
locator:
enabled: true # gateway 可以从 na