GateWay 网关
一、概述
SpringCloud Gateway 是 SpringCloud 的一个全新项目,基于 Spring5.0+SpringBoot2.0 和 Project Reactor 等技术开发的网关,它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式。
为了提升网关的性能,SpringCloud Gatway 是基于 WebFlux 框架实现的,而 WebFlux 框架底层则使用了高性能的 Reactor 模式通讯框架 Netty。
总的来说:Spring Cloud Gateway 使用的Webflux中的reactor-netty响应式编程组件,底层使用了Netty通讯框架
GateWay 的功能:1. 反向代理,2. 鉴权, 3. 流量控制,4. 熔断,5. 日志监控...等等;
微服务架构中网关所处的位置
GateWay 中三大概念
- Route 路由
路由是构建网关的基本模块,它由ID,目标URI,一系列的断言和过滤器组成,如果断言为true则匹配该路由 - Predicate 断言
参考的是java8的java.util.function.Predicate开发人员可以匹配HTTP请求中的所有内容(例如请求头或请求参数),如果请求与断言相匹配则进行路由 - Filter 过滤器
指的是Spring框架中GatewayFilter的实例,使用过滤器,可以在请求被路由前或者之后对请求进行修改。
GateWay 工作流程
客户端向Spring Cloud Gateway发出请求。然后在Gateway Handler Mapping中找到与请求匹配的路由,将其发送到Gateway Web Handler.
Handler再通过指定的过滤器链来将请求发送给我们实际的服务执行业务逻辑,然后返回。
过滤器之间用虚线分开是因为过滤器可能会在发送代理请求之前("pre")或之后("post")执行业务逻辑。
Filter在"pre"类型的过滤器可以做参数校验、权限校验、流量监控、日志输出、协议转换等,在"post"类型的过滤器中可以做响应内容、响应头的修改,日志的输出,流量控制等有着非常重要的作用
入门案例
- 新建 Maven 工程 cloud-gateway-gateway9527,添加 Maven 依赖
<dependencies>
<!--新增gateway,不需要引入web和actuator模块-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>com.atguigu.springcloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
- 添加 yml 配置,主启动类
server:
port: 9527
spring:
application:
name: cloud-gateway
eureka:
instance:
hostname: cloud-gateway-service
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://localhost:7001/eureka
@SpringBootApplication
@EnableEurekaClient
public class GateWayMain9527 {
public static void main(String[] args) {
SpringApplication.run( GateWayMain9527.class,args);
}
}
- 添加 yml 配置,做网关映射
server:
port: 9527
spring:
application:
name: cloud-gateway
cloud:
gateway:
discovery:
locator:
enabled: true # 开启从注册中心动态创建路由的功能,利用微服务名进行路由
routes:
- id: payment_routh # 路由的ID,没有固定规则但要求唯一,建议配合服务名
uri: http://localhost:8001/ # 匹配后提供服务的路由地址
predicates: # 断言,路径相匹配的进行路由
- Path=/payment/get/**
- id: payment_routh2
uri: lb://cloud-payment-service # 协议为 lb,表示负载均衡
predicates:
- Path=/payment/lb/**
- id: payment_routh3
uri: lb://cloud-payment-service
predicates:
- Path=/payment/after/**
- After=2022-05-19T13:33:10.316+08:00[Asia/Shanghai]
- id: payment_routh4
uri: lb://cloud-payment-service
predicates:
- Path=/payment/cookie/**
- Cookie=username,ayi # 必须携带 cookie,且 username=ayi
- id: payment_routh5
uri: lb://cloud-payment-service
predicates:
- Path=/payment/header/**
- Header=X-Request-Id,\d+ # 必须携带 header,且 X-Request-Id=(整数)
eureka:
instance:
hostname: cloud-gateway-service
client:
service-url:
register-with-eureka: true
fetch-registry: true
defaultZone: http://localhost:7001/eureka
- 测试
启动7001:cloud-eureka-server7001
启动8001:cloud-provider-payment8001
启动9527网关:cloud-gateway-gateway9527
访问:
GateWay 实现动态路由
默认情况下Gateway会根据注册中心的服务列表,以注册中心上微服务名为路径创建动态路由进行转发,从而实现动态路由的功能
spring:
application:
name: cloud-gateway
cloud:
gateway:
discovery:
locator:
enabled: true # 开启从注册中心动态创建路由的功能,利用微服务名进行路由
routes:
- id: payment_routh # 路由的ID,没有固定规则但要求唯一,建议配合服务名
uri: lb://cloud-payment-service # 匹配后提供服务的路由地址
predicates: # 断言,路径相匹配的进行路由
- Path=/payment/get/**
Predicate 的使用
Predicate 有多种:
- After:在某一时刻之后访问才可放行:2022-05-19T13:33:10.316+08:00[Asia/Shanghai]
日期格式为 java 中
ZonedDateTime zonedDateTime = ZonedDateTime.now();
System.out.println(zonedDateTime);
- Before:和 After 用法类似
- Between:两个时刻之间才可访问,日期之间中逗号隔开
- Cookie:必须携带某个 Cookie 才可放行
- Header:必须携带某个请求头才可放行
- Host:主机名必须满足正则匹配才可放行
- Method:必须满足相应的请求方法才可放行
- Path:请求的 uri 必须满足正则匹配才可放行
- Query:请求必须携带某个参数才可放行
spring:
application:
name: cloud-gateway
cloud:
gateway:
discovery:
locator:
enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
routes:
- id: payment_routh #路由的ID,没有固定规则但要求唯一,建议配合服务名
#uri: http://localhost:8001 #匹配后提供服务的路由地址
uri: lb://cloud-payment-service
predicates:
- Path=/payment/get/** #断言,路径相匹配的进行路由
- id: payment_routh2
#uri: http://localhost:8001 #匹配后提供服务的路由地址
uri: lb://cloud-payment-service
predicates:
- Path=/payment/lb/** #断言,路径相匹配的进行路由
#- After=2020-03-08T10:59:34.102+08:00[Asia/Shanghai]
#- Cookie=username,zhangshuai #并且Cookie是username=zhangshuai才能访问
#- Header=X-Request-Id, \d+ #请求头中要有X-Request-Id属性并且值为整数的正则表达式
#- Host=**.atguigu.com
#- Method=GET
#- Query=username, \d+ #要有参数名称并且是正整数才能路由