GateWay
1.网关
网关是服务的守门神, 所有微服务的统一入口
网关核心功能:
- 请求路由: 一切请求都必须先经过gateway, 但网关不处理业务, 而是根据设置的规则, 将请求转发给某个微服务, 这个过程叫做路由, 当路由的目标服务存在多个时, 还需要做负载均衡
- 权限控制: 网关作为微服务入口, 需要校验用户是否有请求资格, 如果没有则拦截
- 限流: 当请求流量过高, 在网关中按照微服务能接受的速度来放行请求, 避免服务压力过大
2.GateWay
2.1 核心概念
- 路由
- 断言
- 过滤器
2.2 初体验
2.2.1 创建父工程
- 步骤一: 将packaging修改为pom
<packaging>pom</packaging>
- 步骤二: 引入依赖和设置properties
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.12.RELEASE</version>
</parent>
<properties>
<maven.compiler.source>14</maven.compiler.source>
<maven.compiler.target>14</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring-cloud-dependencies.version>Hoxton.SR12</spring-cloud-dependencies.version>
<spring.cloud.alibaba.version>2.2.7.RELEASE</spring.cloud.alibaba.version>
</properties>
<dependencyManagement>
<dependencies>
<!--spring-cloud统一的依赖管理器-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud-dependencies.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<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>
父工程的pom.xml中只需要定义依赖的版本信息, 不需要真正的引入依赖, 所以使用<dependencyManagement>
, 在这里我们定义了三个版本依赖
- SpringBoot的版本
- SpringCloud的版本
- SpringCloudAlibaba的版本
这三个版本是不能随意定义的, 他们存在对应的关系
springboot,springCloud,springCloudAlibaba各版本之间的对应关系
在这边定义好了后, 之后使用到的SpringBoot组件、SpringCloud组件、SpringCloudAlibaba组件, 都可以不写版本号
扩展知识: POM工程的作用
- 聚合: 在父模块中配置与子模块的关系,聚合可以感知到参与聚合的模块有哪些, 当我们最父模块进行clean操作, 会依次对子模块也clean
- 继承: 继承描述的是两个工程间的关系,与java中的继承相似,子工程可以继承父工程中的配置信息,常见于依赖关系的继承
- 减少重复配置
- 减少版本冲突(在父工程改一下,所有子模块的版本都跟着动)
2.2.2 gateway工程
- 步骤一: 引入依赖
spring-cloud组件, 版本依赖于父工程中配置的spring-cloud版本号, 所以此处不需要填版本号
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
- 步骤二: 配置application.yml
server:
port: 8088 # 网关端口
spring:
application:
name: gateway # 服务名称
cloud:
gateway:
routes: # 网关路由配置
- id: order-service # 路由唯一标识, 自定义, 唯一即可
uri: http://localhost:8020 # 路由的目标地址(请求转发的地址)
predicates: # 断言, 判断请求是否断言条件, 如果满足则进行路由
- Path=/order-service/** # 按路径匹配, 只要以/order-service/开头就符合路由规则
filters: # 过滤器
# 因为order服务没有/order-service这个路径, StripPrefix参数表示从请求中剥离的路径个数 ↓
# 剥离之后 > http://localhost:8020/order/add
- StripPrefix=1
- 步骤三: 添加引导类, 并启动服务
@SpringBootApplication
public class GatewayApp {
public static void main(String[] args) {
SpringApplication.run(GwApp.class, args);
}
}
2.2.3 order工程
- 步骤一: 引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
- 步骤二: application.yml
server:
port: 8020
- 步骤三: 添加引导类以及响应类, 并启动服务
@SpringBootApplication
public class OrderApp {
public static void main(String[] args) {
SpringApplication.run(OrderApp.class, args);
}
}
@RestController
@RequestMapping("order")
public class OrderController {
@GetMapping("add")
public String add() {
return "order add success";
}
}
order服务占用的端口是8020, 我们可以直接调用这个接口
2.2.4 测试网关路由
访问http://localhost:8088/order-service/order/add
, 路由成功
网关中并没有帮我们实现任何API, 那它是如何实现的呢?
具体流程:
- 用户请求
localhost:8088/order-service/order/add
访问网关服务, 根据配置的路由规则, 符合-Path=/order-service/**
, 确认是路由到order-service
- 又因为我们设置了过滤第一个路径, 所以URI为
/order/add
, 最终路由到localhost:8020/order/add
2.2.5 GateWay整合nacos
- 步骤一: 在gateway、order服务中引入Nacos客户端依赖
<!-- nacos客户端起步依赖(Nacos服务注册发现依赖) -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
- 步骤二: 连接Nacos, 注册服务
spring:
cloud:
# nacos
nacos:
discovery:
server-addr: 127.0.0.1:8848
- 步骤三: 重新启动gateway、order服务
- 步骤四: 修改路由地址, 从硬编码修改为服务名称
使用了lb://前缀来指定负载均衡的方式
- 步骤五: 更简单的配置(直接使用nacos中的服务名称进行访问)
不在配置路由规则(routes), 而是直接启用自动识别, 会自动识别nacos中的服务名称
当然这种方式比较少用到, 但是可以了解了解
3.断言工厂
我们在配置文件中写的断言规则都是字符串, 这些字符串会被Predicate Factory读取并解析, 转变为路由的判断条件
名称 | 说明 | 示例 |
---|---|---|
After | 是某个时间点后的请求 | - After=2037-01-20T17:42:47.789-07:00[America/Denver] |
Before | 是某个时间点之前的请求 | - Before=2031-04-13T15:14:47.433+08:00[Asia/Shanghai] |
Between | 是某两个时间点之前的请求 | - Between=2037-01-20T17:42:47.789-07:00[America/Denver], 2037-01-21T17:42:47.789-07:00[America/Denver] |
Cookie | 请求必须包含某些cookie | - Cookie=chocolate, ch.p |
Header | 请求必须包含某些header | - Header=X-Request-Id, \d+ |
Host | 请求必须是访问某个host(域名) | - Host=.somehost.org,.anotherhost.org |
Method | 请求方式必须是指定方式 | - Method=GET,POST |
Path | 请求路径必须符合指定规则 | - Path=/red/{segment},/blue/** |
Query | 请求参数必须包含指定参数 | - Query=name, Jack或者- Query=name |
RemoteAddr | 请求者的ip必须是指定范围 | - RemoteAddr=192.168.1.1/24 |
4.过滤器工厂
Spring提供了31种不同的路由过滤器工厂。例如:
名称 | 说明 |
---|---|
AddRequestHeader | 给当前请求添加一个请求头 |
RemoveRequestHeader | 移除请求中的一个请求头 |
AddResponseHeader | 给响应结果中添加一个响应头 |
RemoveResponseHeader | 从响应结果中移除有一个响应头 |
RequestRateLimiter | 限制请求的流量 |