目录
创建主启动类GateWayApplication20000.java
SpringCloud Gateway
看一个需求,引出网关服务
1、有一个前后端分离项目, 分析如图
2、使用网关服务, 重构项目架构
Gateway 网络拓扑图-背下来
Gateway 是什么
1. Gateway 是在Spring 生态系统之上构建的API 网关服务,基于Spring ,Spring Boot 和Project
Reactor 等技术。
2. Gateway 旨在提供一种简单而有效的方式来对API 进行路由,以及提供一些强大的过滤器能,
例如∶熔断、限流、重试等.
官网
https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/html/
Gateway 核心功能
1 鉴权
2 流量控制
3 熔断
4 日志监控
5 反向代理
Gateway VS Zuul
Gateway 和Zuul 区别
1. SpringCloud Gateway 作为Spring Cloud 生态系统中的网关,目标是替代Zuul.
2. SpringCloud Gateway 是基于Spring WebFlux 框架实现的.
3. Spring WebFlux 框架底层则使用了高性能的Reactor 模式通信框架Netty , 提升了网关性能.
Gateway 特性
Spring Cloud Gateway 基于Spring Framework(支持Spring WebFlux),Project Reactor 和Spring Boot 进行构建,具有如下特性:
1.动态路由.
2.可以对路由指定Predicate(断言)和Filter(过滤器)
3. 集成Hystrix的断路器功能
4.集成Spring Cloud 服务发现功能
5.请求限流功能
6.支持路径重写
Gateway 基本原理

解读:
1. web 请求,通过一些匹配条件,定位到真正的服务节点/微服务模块,在这个转发过程的前后,进行一些精细化控制。
2. predicate: 就是匹配条件.
3. filter: 可以理解为是网关的过滤机制。有了predicate 和filter,再加上目标URL.就可以实现一个具体的路由.
Route(路由)
一句话: 路由是构建网关的基本模块,它由ID,目标URI,一系列的断言和过滤器组成,如果断言为true 则匹配该路由.
Predicate(断言)
1、一句话: 对HTTP 请求中的所有内容(例如请求头或请求参数)进行匹配,如果请求与断言相匹配则进行路由.
2、简单举例, 比如配置路径, - Path=/member/get/** #断言,路径相匹配的进行路由转发, 如果Http 请求的路径不匹配, 则不进行路由转发.
Filter(过滤)
1、一句话: 使用过滤器,可以在请求被路由前或者之后对请求进行处理
2、你可以理解成, 在对Http 请求断言匹配成功后, 可以通过网关的过滤机制, 对Http 请求处理
简单举例:
filters:
- AddRequestParameter=color, blue #过滤器在匹配的请求头加上一对请求头,名称
为color 值为blue
, 比如原来的http 请求是http://localhost:10000/member/get/1 ==过滤器处理=>
http://localhost:10000/member/get/1?color=blue
How It Works 工作机制
梳理流程(how to work)
1. 客户端向Spring Cloud Gateway 发出请求。然后在Gateway Handler Mapping 中找到与请求相匹配的路由,将其发送到Gateway Web Handler。
2. Handler 再通过指定的过滤器链来将请求发送到我们实际的服务执行业务逻辑,然后返回。
3. 过滤器之间用虚线分开是因为过滤器可能会在发送代理请求之前("pre")或之后("post")执行业务逻辑。
4. Filter 在"pre"类型的过滤器可以做参数校验、权限校验、流量监控、日志输出、协议转换等,
5. 在"post"类型的过滤器中可以做响应内容、响应头的修改,日志的输出,流量监控等有着非常重要的作用。..........................
一句话说:路由转发+执行过滤器链
搭建Gateway 微服务
引入Gateway 项目架构
解读
1. 通过网关暴露的接口,实现调用真正的服务
2. 网关本身也是一个微服务模块
代码实现
1. 参考member-service-consumer-80 创建e-commerce-gateway-20000(具体步骤参考以前)
2. 修改pom.xml, 部分内容可以从member-service-consumer-80 的pom.xml 拷贝
<artifactId>e-commerce-gateway-20000</artifactId>
<!--引入相关的依赖: 我们引入了当前需要的依赖,后面如果有其它需要,再灵活调整-->
<dependencies>
<!--引入gateway-starter 网关场景启动器starter: 使用版本仲裁-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!--引入eureka client 场景启动器starter-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!--特别说明:
1. 不要引入spring-boot-starter-web 和 spring-boot-starter-actuator
否则会出现冲突
2. 因为gateway 是一个服务网关,不需要web...
-->
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!--引入e_commerce_center-common-api-->
<dependency>
<groupId>com.wyxedu.springcloud</groupId>
<artifactId>e_commerce_center-common-api</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
特别说明:
1. 不要引入spring-boot-starter-web 和 spring-boot-starter-actuator否则会出现冲突
2. 因为gateway 是一个服务网关,不需要web..
创建application.yml(重点核心) 内容如下:
server:
port: 20000
spring:
application:
name: e-commerce-gateway
cloud:
gateway:
routes: #配置路由,可以配置多个路由 List<RouteDefinition> routes
- id: member_route01 #路由的id, 程序员自己配置,要求唯一
#gateway 最终访问的url 是 url=uri+Path
#匹配后提供服务的路由地址: 也可以是外网 http://www.baidu.com
#比如: 客户端/浏览器请求 url http://localhost:20000/member/get/1
#如果根据Path匹配成功 最终访问的url/转发url 就是 url=http://localhost:10000/member/get/1
#如果匹配失败, 则有gateway返回404信息
#疑问: 这里配置的 uri 是固定,在当前这种情况其实可以没有有Eureka Server,后面会使用灵活方式
# 配置,就会使用到Eureka Server
uri: http://localhost:10000
predicates: #断言,可以有多种形式
- Path=/member/get/**
- id: member_route02 #路由的id, 程序员自己配置,要求唯一
uri: http://localhost:10000
predicates: #断言,可以有多种形式
#这时如果客户端/浏览器 访问gateway 的url http://localhost:20000/member/save
#匹配Path成功 最终访问的url 就是 http://localhost:10000/member/save
- Path=/member/save
#配置Eureak-Client
eureka:
instance:
hostname: e-commerce-service #先配置着
client:
register-with-eureka: true #将自己注册到Eureka-Server
fetch-registry: true
service-url:
#表示将自己注册到哪个eureka-server
#这里为了方便,使用Eureka Server的单机环境测试
defaultZone: http://eureka9001.com:9001/eureka
创建主启动类GateWayApplication20000.java
@SpringBootApplication
@EnableEurekaClient
public class GateWayApplication20000 {
public static void main(String[] args) {
SpringApplication.run(GateWayApplication20000.class,args);
}
}
测试
1 启动e-commerce-eureka-server-9001
2 启动member-service-provider-10000
3 启动e-commerce-gateway-20000
4 浏览器:(通过网关访问) http://localhost:20000/member/get/1
Postman 测试添加(走网关)
请求地址: http://localhost:20000/member/save
json 数据:
{
"name": "天山童姥",
"pwd": "hello",
"mobile": "110",
"email": "zz@sohu.com",
"gender": 2
}
注意事项和细节
1. 因为我们的端口号10000的member 的controller 的方法参数使用了@RequestBody
@PostMapping(value = "/member/save")
public Result save(@RequestBody Member member) {//增加
log.info("会员服务方接收到member= " + member);
int result = memberService.save(member);
log.info("reset= " + result);
if (result > 0) { //成功
return Result.success("添加用户成功member-service-provider-10000", result);
} else {
return Result.error("401", "添加用户失败");
}
}
2. 所以,在使用postman 时,需要使用json 格式发送数据, 否则会报400 错误.
3. 回顾:@RequestBody 的作用是: 将前端发送的json 数据封装成对象, 如果发送的不是json 数
据,会报错误.