浅谈Spring Cloud Gateway技术
Posted 敲代码的小小酥
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了浅谈Spring Cloud Gateway技术相关的知识,希望对你有一定的参考价值。
前言
关于Gateway技术的详细使用,在这里不再记录,官网和其他博客写的很清楚,本篇博客主要是记录一些在学习Gateway时产生的一些问题和理解。便于更深刻的理解Gateway这门技术。
Gateway官网
Gateway详细使用
一、对于Gateway的整体理解
Gateway作为一门微服务的网关技术,用于取代Zuul。所以,在官网和大多数博客总结中,并没有详细解释到底微服务网关是用来做什么的,而是默认为学者都是从熟悉Zuul技术转向学习Gateway技术,直接开始比较Zuul和Gateway的异同。
而对于向博主这样的没有接触过Zuul,甚至没有接触过一丁点微服务网关技术的学者而言,上述这种讲解Gateway的方式就显得很突兀。以至于在刚刚学习Gateway的时候,有种无法驾驭的感觉。
所以,在学习Gateway技术之前,首先需要对其有个自己能够接受的理解,而不是一堆官方的专业术语。
博主对Gateway的理解是这样的:
在vue脚手架工程中,有路由技术,vue中的路由技术是很好理解的。因为vue项目是单页面工程,一个页面中,要展现不同的vue组件。要展示哪个vue组件,就是通过配置路由进行组件跳转的。而且在路由中,有路由守卫的概念,在跳转到路由组件之前或之后,可以通过路由守卫进行一些操作。
类比vue中的路由,微服务中的网关,也是同样的作用。一个微服务工程中,每个微服务就相当于是vue中的一个组件。需要配置映射路径,来告诉网关,跳到哪个微服务上去。同时,Gateway网关也提供了类似于路由守卫的功能,在跳转到微服务之前或之后,可以进行一些操作。这样理解Gateway网关技术,就容易多了。
二、关于路由、断言、过滤器概念的理解
同样的,在官网和绝大多数博客中,都是先甩出了这几个概念,来告诉学者,这些是Gateway的核心。而对于像博主这样第一次接触微服务网关技术的人来说,这种介绍方式简直就是劝退。
还是类比vue的路由来说这几个概念。在vue中,需要在router.js里配置路由的路径,来进行组件跳转的映射。同理,在Gateway网关中,也需要配置映射,来进行微服务的跳转。路由,断言和过滤器,就是配置跳转微服务的映射信息。
在yml中配置,配置如下:
#截取部分代码,主要体现这三个概念其实就是一个配置
routes: #这就是路由的概念
- id: order_route #路由ID,全局唯一,建议配合服务名
uri: lb://mall-order #lb 整合负载均衡器ribbon,loadbalancer
predicates: #这就是断言的概念
#Path路径匹配
- Path=/order/**
filters: #这就是过滤器的概念
通过上面的配置可以看出,其配置的格式,跟vue中路由配置的格式都很相似。routes路由配置项里面可以定义多个路由跳转,id是某个路由跳转的唯一标识,uri是跳转到微服务的路径,类似于vue路由配置项的component属性。predicates断言就是客户端发送什么请求,要路由转发到uri配置的微服务中去,类似于vue路由配置项中的path属性。filters过滤器就类似于vue路由配置中的独享守卫配置,在Gateway网关转发到对应微服务组件之前和之后,做一些操作。下面附上一个vue路由的配置,更直观明了:
path: '/HelloHello',
component: HelloHello,
beforeEnter(to,from,next)//独享守卫
if(to.path==="/test")
alert("请登录");
next(false); // 禁止跳转
else
next()
三、对Gateway的再次理解
上述通过类比的方法,大体对Gateway有了个清晰的认识。而当看到官网上的这张图之后,博主对Gateway的理解可以说是更深入了一层。
这是一个Gateway的工作流程图,看到这个图后,博主的第一反应是,Gateway的设计是不是抄袭了SpringMVC?
首先,复习一下SpringMVC对请求的处理流程。简单来说,就是SpringMVC拿到一个请求后,通过HandlerMapping找映射,找到能处理这个请求的Handler。Handler是如何处理这个请求的呢?因为SpringMVC想要的是ModelAndView对象,所以,Handler就找了HandlerAdapter来做适配器,将传进来的request对象,适配成ModelAndVIew对象。这就是适配器设计模式。而我们定义的Controller,就是HandlerAdapter适配器的一种。在获取到适配器HandlerAdapter后,SpringMVC会执行其前置拦截器,中置拦截器和后置拦截器以及适配器本身。自此,一个请求处理完成。详情可参考博主的另一篇文章:从DispatcherServlet源码分析SpringMVC处理请求的流程
回到Gateway中,从上图可以看出,客户端发送请求到Gateway后,也是通过HandlerMapping进行映射,然后找到对应的Handler。Handler处理该请求时,先是执行该请求的pre过滤器,类似于SpringMVC中的前置拦截器,然后请求到达微服务,执行完微服务的逻辑后,response返回了Gateway中,执行Gateway中post拦截器,类似于SpringMVC中的后置拦截器,然后把response返回给客户端。
所以说,Gateway工作流程的设计,与SpringMVC处理请求的流程,有异曲同工之处。从这个角度来说,可以把Gateway理解成一个MVC框架,只不过这个MVC框架,处理的是所有微服务的请求,是一个统一入口和出口。如果把整个微服务看出一个单体项目的话,那么Gateway网关,就是这个单体项目的Controller层,而其他的微服务,类似于单体项目中的service层和dao层。
关于过滤器,这里摘抄一段,加深理解和应用:
PRE:这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试信息等。
POST:这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的 HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端等。
四、Gateway提供断言和过滤器都有哪些
虽然Gateway允许我们自定义断言和过滤器,但是在绝大多数场景中,Gateway为我们提供的断言和过滤器都可以满足需求,所以这里单独过一遍Gateway为我们提供好的断言和过滤器都有哪些,以便于在工作中,遇到相应场景时可以直接使用,而不是再费力不讨好的重新自定义一个。
这里只是记录一下都有哪些断言和过滤器,具体的使用方法,请参考官网或其他博客。
断言:
-
After、Before、Between:在某个时间之后,之前或之间,才能路由到某个微服务上,否则不能进行路由,返回报404.
-
Cookie断言:请求带有某个cookie(正则匹配),则进行路由转发
-
Header断言:请求带有某个Header(正则匹配),则进行路由转发
-
Host断言:请求的Host属性匹配,则进行转发
-
Method断言:请求方式是Get/Post等,则进行路由转发
-
Path断言:请求路径匹配,则进行路由转发
-
Query断言:请求带有某个参数,则进行路由转发
-
RemoteAddr断言:请求来自某个ip,则进行路由转发
-
Weight权重断言:百分之多少请求会路由到某个微服务。
过滤器:
Gateway的过滤器分为局部过滤器和全局过滤器。局部过滤器需要自己配置才生效,全局过滤器无需配置,自动生效。过滤器无非就是对request和response做一些操作,例如认证等操作。
这里需要注意的是,Gateway已经提供了一个限流过滤器,利用的是令牌桶算法。那么,为什么还要和Sentinel进行结合使用呢?这么做的目的是什么呢?
Gateway提供的限流过滤器,需要配置redis,通过redis+lua脚本实现,可以进行
ip限流:某个ip进行限流
用户限流:通过userId参数限流;
接口限流:某个接口进行限流;
关于令牌桶算法的原理,参考这篇文章:spring-cloud-gateway限流实现原理
至于Gateway已经提供了限流算法,为何还要与Sentinel结合使用呢?博主初步猜想是Gateway提供的限流功能比较单一,而Sentinel是专注于流量的工具,提供了更多的功能,还有可视化UI界面,所以利用Sentinel限流更方便。等研究Sentinel技术时,再回答此问题。以及结合Sentinel后,还是否有比较再配置Gateway的限流过滤器,以及是否冲突等问题,等学习完Sentinel后,再来解答。
五、Gateway高可用
Gateway在微服务项目中,是一个单独的微服务,这个微服务里,定义路由,断言,过滤器,配置路由的转发等等。这个微服务不涉及任何业务代码。所以,由此看来,Gateway也是微服务实例中的一员。其并不是和nacos一样是一个单独运行的程序,而是一个微服务,也会被注册到注册中心去。Gateway也是一个客户端上路由请求的转发,有点儿类似于Ribbon那种感觉。
如果Gateway这个微服务挂了,那么整个路由规则就挂了,这个问题是很严重的,所以,Gateway需要高可用。高可用就是部署多个Gateway实例。而Gateway微服务实例和其他业务的微服务实例不同的是,Gateway微服务是需要与客户端请求进行交互的,所以需要在nginx中配置Gateway的负载均衡,来防止一个Gateway实例异常后,可以高可用。
六、Gateway动态路由与规则持久化
SpringCloud Gateway 动态路由
Gateway默认是基于内存的路由保存,即从配置文件中读取信息,将路由保存到内存中。这样的弊端就是无法动态添加或修改路由,只能通过重启路由使其生效。于是出现了动态路由,将路由信息持久化到数据库,并支持实时的添加和修改。
要理解Gateway动态路由,需要精通其源码流程。这里我们不做详细解释。其大致原理就是,利用@ConditionOnMissing注解,如果没有持久化的路由定位器,则加载内存路由定位器。所以,我们不配置持久化的路由定位器时,默认是基于内存的。想实现持久化,就自己定义一个持久化路由定位器即可。码云上已经有了基于Mogodb的持久化实现。
七、Gateway生产环境部署
其他微服务都可以打成war包,放在tomcat里运行。而Gateway微服务必须使用内置的tomcat运行,不能打成war包放在tomcat里运行。因为Gateway是基于netty的webflux运行的,其和外置的tomcat有冲突。
以上是关于浅谈Spring Cloud Gateway技术的主要内容,如果未能解决你的问题,请参考以下文章
十一、Spring Cloud Gateway-Actuator API
spring cloud 2.x版本 Gateway路由网关教程