概述
Gateway是SpringCloud下的新一代服务网关,用以取代之前的NetFlix的Zuul网关
简介
Gateway是在Spring生态系统之上构建的API网关服务,基于Spring 5,Spring Boot 2和 Project Reactor等技术。
Gateway旨在提供一种简单而有效的方式来对API进行路由,以及提供一些强大的过滤器功能, 例如:熔断、限流、重试等
为了提升网关的性能,SpringCloud Gateway是基于WebFlux框架实现的,而WebFlux框架底层则使用了高性能的Reactor模式通信框架Netty。
功能
- 反向代理
- 鉴权
- 流量控制
- 熔断
- 日志监控
- ….
- 网关在架构中所处的位置
Gateway对比Zuul
- Zuul 1.x 基于Servlet 2. 5使用阻塞架构
- Zuul 2.x理念更先进,想基于Netty非阻塞和支持长连接,但SpringCloud目前还没有整合
- Spring Cloud Gateway 建立 在 Spring Framework 5、 Project Reactor 和 Spring Boot 2 之上, 使用非阻塞 API。
三大核心概念
- Route(路由):构建网关的基本模块,由ID,目标URI,一系列断言以及过滤器组成,如果断言为真则匹配该路由
- Predicate(断言):Java8函数式接口Predicate。接口的输入类型是ServerWebExchange。可以匹配Http请求中的所有内容,比如请求头和请求参数。如果断言和请求相匹配则进行路由。
- Filter(过滤):GatewayFilter特定工厂构建的实例,使用过滤器,可以在请求被路由之前或者之后对请求进行修改
Gateway工作流程
- 官网资料
也即:路由转发+执行过滤器链
入门配置
新建Module:cloud-gateway-gateway9527
修改pom文件:不能引入web模块,否则会报错
<dependencies>
<!--gateway-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!--eureka-client-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!-- 引入自己定义的api通用包,可以使用Payment支付Entity -->
<dependency>
<groupId>top.chasingwind</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>${project.version}</version>
</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>
- 配置文件
这里是基础配置,还未涉及URI,断言以及过滤
- 主启动类
- 到这里这个模块就可以启动了,但是只是一个普通的SpringBoot模块,那么如何做路由映射?
之前我们的服务8001模块,访问地址为
如果我们想要隐藏8001端口,可以通过网关进行配置
修改配置文件
predicate对应的请求路径
通过9527访问8001端口
这样就相当于在微服务模块之前再添加一层网关模块
- 存在的问题
提供服务的路由写死了。如果是单机可以这么做,但是集群的话就不能写死。
应该通过负载均衡,采用服务名的方式来进行路由匹配。
默认情况下,Gateway会根据注册中心注册的服务列表,以注册中心上微服务名为路径创建动态路由进行转发,进而实现动态路由的功能。
修改配置文件
通过9527端口进行访问,发现同时实现了负载均衡
解释一下uri前面的lb的意思
所以上面访问的时候会有负载均衡的现象出现
Gateway常用的Predicate
- Predicate是什么
用于匹配不同的Http请求属性,如果和请求相匹配,则使用当前配置进行路由
- 有哪些Predicate
查看Gateway模块启动信息
官网介绍Predicate
- The After Route Predicate Factory:用于判断请求时间是否在设置的时间之后,时间是
ZonedDatetime
类型
测试
当前时间晚于配置的时间,可以正常进行路由
修改配置文件中的时间,大于当前时间(请求时间)
再次进行访问测试,直接报错
- The Before Route Predicate Factory:用于判断请求时间是否在设置的时间之前,时间是
ZonedDatetime
类型
- The Between Route Predicate Factory:用于判断请求时间是否在设置的时间之间,时间是
ZonedDatetime
类型eg:两个时间用“,”隔开
- The Cookie Route Predicate Factory:请求的Cookie是否包含配置的Cookie项,并且值也需要匹配
配置
当Cookie只有配置的cookie,可以正常访问
当Cookie包含配置的cookie,可以正常访问
当Cookie不包含配置的cookie,直接报错
当Cookie包含配置的cookie,但是值不相等,直接报错
- The Host Route Predicate Factory:匹配请求头中的Host参数
Gateway中的Filter
- 是什么
Filter分类
- 生命周期:pre和post
- 种类:Gateway Filter,Global Filters
作用
- 一般用于进行请求记录或者鉴权等等
- 作用时机
在Predicate匹配之后进行路由之后
- 自定义Filter
需要实现两个接口
测试
当不符合过滤器过滤的时候,直接返回请求,根本进不到后面的服务代码
postman返回值为空,页面是浏览器根据406状态码进行渲染得到的