Gateway新一代网关
Posted 杀手不太冷!
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Gateway新一代网关相关的知识,希望对你有一定的参考价值。
文章目录
Gateway新一代网关
整体思维导图
Gateway基本概念
Cloud全家桶中有个很重要的组件就是网关,在1.x版本中都是采用的Zuul网关;
但在2.x版本中,zuul的升级一直跳票,SpringCloud最后自己研发了一个网关替代Zuul,
那就是SpringCloud Gateway一句话:gateway是原zuul1.x版的替代。
SpringCloud Gateway是Spring Cloud的一个全新项目,基于Spring 5.0+Spring Boot2.0和Project Reactor等技术开发的网关,它旨在微服务架构提供一种简单有效的统一的API路由管理方式。SpringCloud Gateway作为Spring Cloud生态系统中的网关,目标是替代Zuul,在Spring Cloud 2.0以上版本中,没有对新版本的Zuul 2.0以上最新高性能版本进行集成,仍然还是使用的Zuul 1.x非Reactor模式的老版本。而为了提升网关的性能,SpringCloud Gateway是基于WebFlux框架实现的,而WebFlux框架底层则使用了高性能的Reactor模式通信框架Netty。
Spring Cloud Gateway的目标提供统一的路由方式且基于Filter链的方式提供了网关的基本的功能,例如:安全,监控/指标,和限流。
从上图中可以看出,网关其实就是挡在调用的微服务的前面,就比如说你现在有一个请求,这个请求会通过负载均衡调用远程的一个服务器,那么这个时候这个请求会先被网关处理,然后才会调用远程服务器上的具体的微服务。
有Zuul了怎么又出来了gateway
一方面因为Zuul1.0已经进入了维护阶段,而且Gateway是SpringCloud团队研发的,是亲儿子产品,值得信赖。而且很多功能Zuul都没有Gateway用起来简单便捷。
Gateway是基于异步非阻塞模型上进行开发的,性能方面不需要担心。虽然Netflix早就发布了最新的Zuul 2.x,但Spring Cloud貌似没有整合计划。而且Netflix相关组件都宣布进入维护期;不知前景如何?
多方面综合考虑Gateway是很理想的网关选择。
SpringCloud Gateway与Zuul的区别
Spring Cloud Gateway具有如下特征:
基于Spring Framework 5,Project Reactor和Spring Boot 2.0进行构建;
动态路由:能够匹配任何请求属性;
可以对路由指定Predicate(断言)和Filter(过滤器);
集成Hystrix的断路器功能;
集成Spring Cloud服务发现功能;
易于编写的Predicate(断言)和Filter(过滤器);
请求限流功能;
支持路径重写。
区别
在SpringCloud Finchley正式版之前,Spring Cloud推荐的网关是Netflix提供的Zuul;
1.Zuul 1.x是一个基于阻塞I/O的API Gateway(什么是阻塞?什么是非阻塞?阻塞的意思就是说程序卡到一个地方的时候,它会一直等待,知道这个卡着的地方执行完毕,非阻塞的意思就是当你卡住的时候,可以进行异步调用,下面的代码会继续执行)
2.Zuul 1.x基于Servlet 2.5使用阻塞架构它不支持任何长连接(如WebSocket)Zuul的设计模式和nginx较像,每次I/O操作都是从工作线程中选择一个执行,请求线程被阻塞到工作线程完成,但是差别是Nginx用C++实现,Zuul用Java实现,而JVM本身会有第一次加载较慢的情况,使得Zuul的性能相对较差。
3.Zuul 2.x理念更先进,想基于Netty非阻塞和支持长连接,但SpringCloud目前还没有整合。Zuul 2.x的性能较Zuul 1.x有较大提升。在性能方面,根据官方提供的基准测试,Spring Cloud Gateway的RPS(每秒请求数)是Zuul的1.6倍。
4.Spring Cloud Gateway建立在Spring Framework5,Project Reactor和Spring Boot2之上,使用非阻塞API
5.Spring Cloud Gateway还支持WebSocket,并且与Spring紧密集成拥有更好的开发体验。
Gateway三大核心概念
Route(路由)
路由是构建网关的基本模块,它由ID,目标URI,一系列的断言和过滤器组成,如果断言为true则匹配该路由。
请求从外面过来,会先被网关处理,网关会决定该请求会调用哪个微服务,但是这个请求怎么调用呢?所以网关是不是必须要有一个路由器啊,它要可以进行请求的路由转发,具体决定该请求会调用哪个微服务。
Predicate(断言)
参考的是Java8的java.util.function.Predicate开发人员可以匹配HTTP请求中的所有内容(例如
请求头或请求参数),如果请求与断言相匹配则进行路由转发。
什么是断言?就比如说,你现在想进入e签包公司,你胸上挂着e签宝的工牌,那你到底可不可以进来呢?这个就要判断一下你的工牌是不是e签宝的,如果是true你就可以进来,如果你是false就不能够进来。
Filter(过滤)
指的是Spring框架中GatewayFilter的实例,使用过滤器,可以在请求被路由前或者之后对请求进行修改。
总体
web请求,通过一些匹配条件,定位到真正的服务节点。并在这个转发过程的前后,进行一些精细化控制。predicate就是我们的匹配条件;而fliter,就可以理解为一个无所不能的拦截器。有了这两个元素,再加上目标uri,就可以实现一个具体的路由了。
Gateway工作流程
Gateway的核心逻辑:路由转发+执行过滤器链
客户端向Spring Cloud Gateway发出请求。然后在Gateway Handler Mapping中找到与请求相匹配的路由,将其发送到Gateway Web Handler。
Handler再通过指定的过滤器链来将请求发送到我们实际的服务执行业务逻辑,然后返回。
过滤器之间用虚线分开是因为过滤器可能会在发送代理请求之前(“pre”)或之后(“post”)执行业务逻辑。
Filter在"pre"类型的过滤器可以做参数校验,权限校验,流量监控,日志输出,协议转换等,在"post"类型的过滤器中可以做响应内容,响应头的修改,日志的输出,流量监控等有着非常重要的作用。
Gateway9527搭建
新建Module
POM
YML
业务类
网关微服务是挡在微服务外面的微服务,不需要有业务类。
主启动类
YML新增网关配置
此段配置就相当于是一个predicate断言,如果匹配的路径是http://localhost:8001/payment/get/**那么断言为true,网关会进行路由转发,会去访问http://localhost:8001/payment/get/的地址,但是通过网关访问微服务用的是网关自己的端口号9527,而不是提供者的端口号8001,使用网关的时候会淡化真正的提供者服务的端口号,也即是说在浏览器里面输入地址localhost:9527/…的时候,网关会先看一下9527后面的具体的请求是否和配置文件里面配置的断言一致,如果一致那么断言为true,那么网关会进行路由转发去访问localhost:8001/…对应的地址。
测试
首先启动Eureka7001/7002,8001,9527微服务,如下图:
然后提供者服务8001和网关微服务9527都会注入到Eureka注册中心中去,如下图:
然后如果要是没有网关的话,那么我们访问提供者服务8001的接口地址就是用提供者本身的端口号8001,如下图:
但是有了网关之后,我们就逐渐淡化了真实的提供者服务的端口号,而是使用网关的端口号去访问真实的提供者服务,因为它内部会进行路由转发,如下图:
上图中的url后面的请求路径是/payment/get/31与配置文件中配置的断言路径一致,因此断言为true,网关会进行路由转发,转发的路径是localhost:8001/payment/get/31
通过配置类的形式配置网关的路由
网关路由的配置一共有两种,第一种是通过配置文件的方式,但是这样会显得配置文件非常的冗余,通过配置文件配置路由如下图:
第二种方式是通过配置文件配置,如:现在我们想要在http://news.baidu.com百度新闻前面加上一个网关。首先来看一下百度新闻的页面,如下图:
首页如下图:
国内新闻如下图:
再来看一下国际新闻如下图:
下面开始写GateWay路由转发的配置类,如下图:
/**
* @Date 2021/10/5 9:34
* @Author 望轩
*/
@Configuration
public class GateWayConfig {
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder){
RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();
routes.route("path_route_atguigu1",
r -> r.path("/guonei")
.uri("http://news.baidu.com")).build();
routes.route("path_route_atguigu2",
r -> r.path("/guoji")
.uri("http://news.baidu.com")).build();
return routes.build();
}
}
测试如下图:
通过微服务名实现动态路由(负载均衡式的路由转发)
我们的提供者服务有多个,但是我们目前写的提供者微服务只能用localhost:8001端口号的这个提供者微服务,已经被我们写死了,我们要修改一下,让网关在具体进行路由转发的时候,可以对转发到的提供者服务进行负载均衡,我们需要修改配置文件,首先需要开启负载均衡对网关的路由转发的支持,如下图:
然后修改之前网关的路由转发的uri地址,地址的格式是:lb://注册中心的提供者微服务的名字
其中协议是lb,表示的是使用负载均衡,具体的uri如下图:
Eureka注册中心的服务如下图:
测试效果如下图:
Predicate的使用
Predicate断言的概念
总结:Predicate断言其实就相当于是一些筛选条件,只有当这些筛选条件过了的时候,网关才会进行路由转发。
Spring Cloud Gateway将路由匹配作为Spring WebFlux HandlerMapping基础架构的一部分。
Spring Cloud Gateway包括许多内置的Route Predicate工厂。所有这些Predicate都与HTTP请求的不同属性匹配。多个Route Predicate工厂可以进行组合
Spring Cloud Gateway创建Route对象时,使用RoutePredicateFactory创建Predicate对象,Predicate对象可以赋值给Route。Spring Cloud Gateway包含许多内置的Route Predicate Factories
所有这些谓词都匹配HTTP请求的不同属性。多种谓词工厂可以组合,并通过逻辑and。
After Route Predicate断言的使用
After Route Predicate断言表示,只有满足在设置时间之后这个条件,网关的路由才会转发,如下图:
我们可以通过一个类得到默认时区的时间格式,如下图:
在yml配置文件中配置After Route Predicate断言之后,那么只有在设置的时刻之后进行路由转发才能够转发成功,测试已经通过了。
Cookie Route Predicate断言的使用
我们在yml配置文件中加上一个Cookie Route Predicate断言,设置只有请求中包含cookie对象username=xuanyuanzy的时候,网关才可以进行路由转发,yml配置文件中的设置如下图:
那么怎么发送带有cookie的请求呢?我们可以用curl测试,也可以用postman测试,但是为了安全,谷歌限制了postman发送带有cookie的请求,所以只能用curl进行测试。
测试如下:
路由规则会通过获取对应的Cookie name值和正则表达式去匹配,如果匹配上就会执行路由,如果没有匹配上则不执行。
由于谷歌的限制,postman发不出带有cookie的请求,所以只能用curl测试,如下图:
测试成功,发现只有带有cookie对象并且cookie对象中有username=xuanyuanzy键值对的时候,路由转发才能成功。
Gateway中的自定义的Filter的使用
Gateway Filter的概念
路由过滤器可用于修改进入的HTTP请求和返回HTTP响应,路由过滤器只能指定路由进行使用。Spring Cloud Gateway内置了多种路由过滤器,他们都由GatewayFilter的工厂类来产生。
自定义Filter
写一个配置类,如下图:
测试:
请求中必须要包含uname请求参数,那么才会进行路由转发,否则不会进行路由转发,如下图:
以上是关于Gateway新一代网关的主要内容,如果未能解决你的问题,请参考以下文章
SpringCloud --- 服务网关 (Gateway)
SpringCloud --- 服务网关 (Gateway)
Spring Cloud Gateway 突发高危漏洞,下一代云原生网关恰逢其时?
#私藏项目实操分享#SpringCloud技术专题「Gateway网关系列」微服务网关服务的Gateway功能配置指南分析