Spring Cloud Gateway

Spring Cloud 2.x 实 现 了 社 区 生 态 下 的 Spring CloudGateway(全称SCG)微服务工程项目交换机工程项目。Spring Cloud Gateway如前所述WebFlux架构合作开发,最终目标是代替掉Zuul。

Spring Cloud Gateway简述

Spring Cloud Gateway主要有两个优点:

①非堵塞,预设采用RxNetty做为积极响应式Web罐子,透过非堵塞形式,借助极少的缓存和天然资源来处置高mammalian允诺,并提高服务工程项目天然资源借助的可扩展性。

②表达式式程式设计西北侧,透过采用Spring WebFlux的表达式式程式设计模式定义路由器西北侧,处置允诺。

Spring Cloud Gateway可与Eureka、Ribbon、Hystrix等模块相互配合采用,如前所述Spring 5的Reactor和Spring Boot 2构筑,采用Netty做为下层通讯架构,全力支持触发器非堵塞程式设计数学模型和积极响应式程式设计架构,化解了Zuul架构的I/O堵塞难题和缓存发散难题。采用Spring WebFlux架构能使Spring Cloud Gateway在高mammalian情景下具有更快的操控性整体表现,挤占更慢的天然资源。

上面是Spring Cloud非官方对Spring Cloud Gateway特点的如是说。

如前所述Spring Framework 5、Reactor和Spring Boot 2.0架构。

依照允诺的特操控性相匹配相关联的路由器。

软件系统Hystrix。

软件系统Spring Cloud DiscoveryClient。

把更易撰写的Predicates和Filters促进作用于某一路由器。

具有一些交换机的高阶机能,如静态路由器、开闭、方向改写。

对于微服务工程项目交换机而言,最核心理念的特点包括路由器和冷却系统监督机制。从机能优点上上看,Spring Cloud Gateway和Zuul具有相近的优点。它都能软件系统Hystrix、Ribbon阻抗平衡及Spring Cloud的原有模块来同时实现附带机能。所以Spring Cloud Gateway的其本质优点还充分体现在下层的通讯架构上,它能如前所述Netty的I/O数据通信和该事件积极响应监督机制来同时实现网络通讯;它的除此之外两大优点就是采用Spring Framework 5的积极响应式程式设计数学模型,容许透过Spring WebFlux同时实现触发器非堵塞优点,在操控性和天然资源借助率上,都有了质的提高。在程式设计范式上,Spring CloudGateway采用表达式式程式设计模式。非官方提供的Spring Cloud Gateway的架构

Spring Cloud Gateway的核心理念概念

简单说明一下架构图中的三个术语。

Filter(冷却系统):和Zuul的冷却系统在概念上类似,能采用Filter拦截和修改允诺,同时实现对上游的积极响应,进行二次处置,同时实现横切与应用无关的机能,如安全、访问超时设置、开闭等机能。

Route(路由器):交换机配置的基本组成模块,和Zuul的路由器配置模块类似。一个Route模块由一个ID、一个最终目标URI、一组断言和一组冷却系统组成。如果断言为真,则路由器相匹配,最终目标URI会被访问。

Predicate(断言):Predicate来自Java 8的接口,它能用来相匹配来自HTTP允诺的任何内容,例如headers或参数。接口包含多种预设方法,并将Predicate组合成复杂的逻辑(与、或、非),能用于接口参数校验、路由器转发判断等。

Spring Cloud Gateway的接入和配置

Spring Cloud Gateway依赖Spring WebFlux提供的Netty运行时环境,所以Spring Boot必须是2.0或者以上版本。基本的Spring Cloud环境配置确认后,主要的接入步骤如下。

1.Maven依赖引入

2.路由器配置形式一:配置文件形式

各字段含义如下。

id:自定义的路由器ID,保持唯一。

uri:最终目标服务工程项目地址。

predicates:路由器条件,Predicate接受一个输入参数,返回一个布尔值结果。

第一个Predicate如前所述URL的形式。配置文件的第一个路由器的配置采用URL形式,配置了一个ID为url-proxy-1的URI代 理 规 则 。路 由 的 规 则 为 :当 访 问 地 址 为http://localhost:8080/csdn/1.jsp时,会路由器到上游地址https://localhost:8010/1.jsp。

第二个Predicate如前所述服务工程项目ID发现的形式。配置文件的第二个路由器的配置采用与注册中心相结合的服务工程项目发现形式,与单个URI的路由器配置相比,区别其实很小,仅在于URI的schema协议不同。单个URI地址的schema协议,一般为HTTP或者HTTPs协议。

3.如前所述代码DSL形式的路由器配置接入

路由器转发机能同样能透过代码来同时实现,我们能在启动类GatewayApplication中添加customRouteLocator方法来定制转发规则,

Spring Cloud Gateway的工作基本原理

客户端向Spring Cloud Gateway发出HTTP允诺后,如果GatewayHandlerMapping 确 定 请 求 与 路 由 匹 配 , 则 将 其 发 送 到 GatewayWebHandler。WebHandler透过该允诺的某一冷却系统链处置允诺。冷却系统 可 以 在 发 送 代 理 请 求 之 前 或 之 后 执 行 逻 辑 。在 Spring CloudGateway的执行流程中,首先执行所有pre filter逻辑,然后进行回源允诺代理。在允诺代理执行完后,执行post filter逻辑。在pre类型的冷却系统中,能同时实现参数校验、权限校验、流量监控、日志输出、协议转换等机能;在post类型的冷却系统中,能同时实现积极响应内容、积极响应头的修改,日志的输出、流量监控等机能。核心理念工作流程

Predicate条件

在Spring Cloud Gateway中,Spring借助Predicate的优点同时实现了各种路由器相匹配规则,透过Header、允诺参数等不同条件来相匹配相关联的路由器。

我们上看Spring Cloud Gateway内置的几种Predicate的采用方法。

在上述配置文件中,如果多种Predicates同时存在于同一个路由器,允诺必须同时满足所有条件才能被这个路由器相匹配。当一个允诺满足多个路由器的Predicate条件时,允诺只会被首个成功相匹配的路由器转发。上面分别对不同规则的路由器相匹配进行解释。

透过允诺方向相匹配(Path Route Predicate)

路由器断言工厂接收一个参数,依照Path定义好的规则来判断访问的URI是否相匹配。配置示例如下:

如果允诺方向符合要求,则此路由器将相匹配,例如/hello/1或者/hello/world。

采用curl测试,命令行输入:

经过测试发现,第一条和第二条命令能正常获取页面返回值,最后一个命令报404错误,证明路由器是透过指定方向来相匹配的。

透过允诺参数相匹配(Query Route Predicate)

路由器断言工厂接收两个参数:一个必需的参数和一个可选的正则表达式。配置示例如下:

在这样的配置中,只要允诺中包含helloworld特性的参数即可相匹配路由器。采用curl测试,命令行输入:

经过测试发现,只要允诺中带有helloworld参数就会相匹配路由器,不带helloworld参数则不会相匹配。还能将Query的值以键值对的形式进行配置,这样在允诺时会对特性值和正则表达式都进行相匹配,键值对相匹配后才会正确执行路由器逻辑。

在上述路由器相匹配中,允诺中包含hello特性并且参数值是以world开头的、长度为三位的字符串,才会进行相匹配和路由器。采用curl测试,命令行输入:

测试能返回正确的页面代码。如果将hello的特性值改为ok,再次访问就会报404错误,证明路由器需要相匹配正则表达式才会进行路由器。

透过允诺方法相匹配

路由器断言工厂接收一个参数,即需要相匹配HTTP方法。透过POST、GET、PUT、DELETE等不同的允诺形式来进行路由器。

采用curl测试(#curl预设以GET的形式去允诺),命令行输入:

测试返回页面代码,证明相匹配到路由器。

我们再以POST的形式允诺测试。

返回404错误表示没有找到,证明没有相匹配上路由器。

透过Header特性相匹配

路由器断言工厂接收两个参数,分别是允诺头名称和正则表达式。

Header Route Predicate和Cookie Route Predicate一样,也是接收2个参数:一个header的特性值和一个正则表达式。这个特性值和正则表达式相匹配则执行。

透过Host路由器相匹配

Spring Cloud Gateway 可 以 根 据 Host 名 进 行 匹 配 转 发 , HostRoute Predicate接收一组参数、一组相匹配的域名列表。它透过参数中的主机地址做为相匹配规则。

采用curl测试,命令行输入:

透过测试以上两种Host设置形式,均可相匹配到host_route,去掉host参数则会报404错误。

时间相匹配

Predicate全力支持设置时间,在允诺转发时,先判断这个时间与我们设置的时间,然后进行转发,所以又细分为设置时间后断言、设置时间前断言、设置时间之间断言。

设置时间后断言:从After Route Predicate Factory中获取一个UTC时间格式的参数,当允诺的当前时间在配置的UTC时间之后,则成功相匹配,否则不能成功相匹配。上面是实例配置:

设置时间前断言:从Before Route Predicate Factory中获取一个UTC时间格式的参数,当允诺的当前时间在配置的UTC时间之前,则成功相匹配,否则不能成功相匹配。上面是实例配置:

设置时间之间断言:从Between Route Predicate Factory中获取一个UTC时间格式的参数,当允诺的当前时间在配置的UTC时间之间,则成功相匹配,否则不能成功相匹配。上面是实例配置:

透过Cookie相匹配

Cookie路由器断言会取两个参数,一个是Cookie name,一个是正则表达式,路由器规则是透过获取的相关联Cookie name值和正则表达式进行相匹配,如果相匹配上就会执行路由器,如果没有相匹配上则不执行。

透过IP地址相匹配

RemoteAddr Route Predicate Factory配置一个IPv4或者IPv6网段的字符串或者IP地址。当允诺的IP地址在网段之内或者与配置的IP地址相同,相匹配成功,则进行转发,否则不进行转发。

能将curl localhost:8080设置为本机的IP地址进行测试,如果允诺的远程地址是192.168.1.30,则此路由器将相匹配。

GatewayFilter与GlobalFilter

Spring Cloud Gateway 中 有 两 种 Filter , 一 种 是GlobalFilter(全局冷却系统),一种是GatewayFilter。GlobalFilter预设对所有路由器有效,GatewayFilter需要透过路由器分组指定。

GlobalFilter接口与GatewayFilter具有相同的签名,是有条件地应用于所有路由器的特殊冷却系统。

当允诺进入路由器相匹配逻辑时,Web Handler会将GlobalFilter的所有实例和所有GatewayFilter路由器某一实例添加到Filter Chain模块。Filter组合执行的顺序由Ordered接口决定,能透过getOrder方法或采用@Order注释来设置。Spring Cloud Gateway透过执行冷却系统将逻辑分为前置和后置阶段,优先级较高的前置冷却系统会优先被执行,而优先级较高的后置冷却系统的执行顺序正好相反,最后执行。

GatewayFilter Factories

冷却系统容许以某种形式修改传入的HTTP允诺或返回的HTTP积极响应。

冷却系统的促进作用域是某些某一路由器。Spring Cloud Gateway包括许多内置的冷却系统工厂。

同时实现前缀修改(增加前缀、去掉前缀)

PrefixPathGatewayFilterFactory及StripPrefixGatewayFilterFactory 是 一 对 处 理 请 求 URL 的 前 缀 的Filter工厂,前者添加前缀,后者去除前缀。

配置文件application.yml

PrefixPathGatewayFilterFactory容许你在相关联的路由器允诺前增加前缀。例如实例配置中的允诺/hello,最后转发到最终目标服务工程项目的方向变为/mypath/hello。

StripPrefixGatewayFilterFactory容许你在相关联的路由器允诺前去除前缀,例如实例配置中的允诺/name/bar/foo,去除前面两个前缀后,最后转发到最终目标服务工程项目的方向为/foo。

同时实现允诺头内容添加和改写

AddRequestHeader GatewayFilter Factory采用一对名称和值做为参数,配置文件application.yml如下:

对于所有相匹配的允诺,将在向下游允诺的头内容中添加xrequest-foo:bar header。

同时实现允诺体内容添加和改写

AddRequestParameter GatewayFilter Factory采用一对名称和值做为参数,配置参数application.yml如下:

对于所有相匹配的允诺,将向下游允诺添加foo=bar查询字符串。

同时实现熔断降级

Hystrix GatewayFilter容许向交换机路由器引入Hystrix,保护服务工程项目不受级联故障的影响,并容许在下游故障时提供fallback积极响应。要在项 目 中 启 用 Hystrix 网 关 过 滤 器 , 需 要 向 Hystrix 的 依 赖 HystrixGatewayFilter Factory添加一个name参数,即HystrixCommand的名称,配置文件application.yml如下:

当调用hystrixfallback时,将转发到/incaseoffailureusethis。注意,这个示例还演示了透过最终目标URI上的lb前缀使Spring Cloud Netflix Ribbon客户端同时实现阻抗平衡。主要情景是交换机应用程序中的内部控制器或处置程序采用fallbackUri,它也能将允诺重新路由器到外部应用程序中的控制器或处置程序。

分布式开闭

SpringCloudGateway内置的

RequestRateLimiterGatewayFilterFactory提供开闭的能力,如前所述令牌桶算法同时实现。目前它内置的RedisRateLimiter,依赖Redis来存储开闭配置和统计数据。当然你也能同时实现自己的RateLimiter,只需同时实现Spring Cloud Gateway 自 带 的 RateLimiter 接 口 或 者 继 承AbstractRateLimiter。

首先,添加Maven依赖。

其次,添加开闭配置。

最后,完成对Path的KeyResolver(能透过KeyResolver来指定开闭的Key),同时实现对某一Path下的开闭控制配置。在冷却系统中能配置一个可选的KeyResolver,KeyResolver在配置中依照名称采用SpEL引用Bean。#{@myKeyResolver}是引用名为pathKeyResolver的Bean的SpEL表达式。KeyResolver接口容许采用可插拔策略来派生限制允诺的Key。代码如下:

Spring Cloud Gateway的静态路由器

上面如是说如前所述Spring Cloud Gateway的静态路由器同时实现(相关代码将会随书附带),同时实现形式与Zuul的静态路由器同时实现形式类似,具有比Zuul更加灵活的路由器策略和相匹配模式。这两种化解方案如下。

透过SpringCloudGateway提供的

GatewayControllerEndpointduan西北侧机能,同时实现路由器的增删改 查 , 或 者 自 己 实 现 ApplicationEventPublisherAware 接口,同时实现自定义的路由器操作方法。具体能参考源代码:GatewayControllerEndpointduan类。

透过同时实现RouteDefinitionRepository接口,同时实现自定义的Repository类,同时实现从数据库或者缓存中静态加载路由器信息的机能。架构模式与Zuul的静态路由器采用相近的路由器加载策略,架构流程

静态路由器思路及化解方案具体如下。

首先,Admin做为前端管理界面,将用户对路由器的添加、修改等操作透过RouteAsynchService存储到DB中。DB中的存储结构如下图所示。

字段映射关系如下。

routeid:标识路由器的唯一ID,能依照路由器ID查找路由器,路由器ID不能重复。

routename:应用名称是标识路由器的别名,是非必选项。

routeorder:相关联RouteDefinition中的order特性。

routestatus:路由器状态,包括编辑、发布、下线等状态。

strategy:路由器策略,和Zuul的路由器策略相近,也全力支持ServiceID策略和URL策略。

predicates:相关联RouteDefinition中的Listpredicates策略集合,以键值对的形式相关联断言策略。

filters:相关联RouteDefinition中的Listfilters集合,以键值对的形式相关联冷却系统策略。

uri:相关联后端服务工程项目,能是后端服务工程项目的ServiceID,也能是服务工程项目的URL地址,与路由器策略相关联。

groupname:标识这个新建的路由器归属在哪个交换机集群上面。

其次,Spring Cloud Gateway的静态路由器管理策略都透过Admin接收对交换机路由器的增删改查命令,然后透过RouteAsynchService将路由器更新服务工程项目mammalian布到相关联的交换机节点,交换机节点从数据库静态获得最新的路由器状态,更新缓存和当前路由器。上面对交换机节点的该事件监听监督机制进行讲解。

说明1#:在代码段中,refreshRoute方法是该事件监听的入口方法,该方法会向Admin管理服务工程项目暴露一个REST服务工程项目。当Admin对路由器进行更改后,会调用refreshRoute方法,触发Spring Cloud Gateway自带的RefreshRoutesEvent该事件,同时设置原子布尔变量routedefine为true,在上面的静态路由器加载中依照该原子布尔变量决定是从数据库中读取路由器还是从缓存中读取路由器。

上面是定制化的核心理念路由器静态加载和缓存管理的关键代码,主要透过同时实现自定义的路由器Repository加载类来静态地加载路由器,透过继承RouteDefinitionRepository父类来提供路由器的配置信息,同时实现逻辑

说明2#:在代码段中,

SagRouteDefinationRepository是自定义的路由器加载同时实现类,这个类同时实现了RouteDefinitionRepository接口。

该接口的源代码如下:

然 后, 跟 进 getRouteDefinitions 方 法, 它是

RouteDefinitionRouteLocator的回调方法,能实时更新路由器信息,

从源代码中调用链路追溯,能发现上面的调用链路:

说明3#:在代码段中,refreshNeed()方法是判断缓存是否失效的标识原子布尔变量,当Admin回调1#代码段中的刷新接口时,会将该失效接口打开。在路由器加载时,如果refreshNeed为false并且routeDefinitions不为空,那么优先加载缓存中的路由器信息。如果refreshNeed为true,那么优先执行加载数据库的操作,透过这段代码的逻辑处置就能保证交换机中路由器的刷新效率和缓存与数据库中路由器信息的同步。

说 明 4 # :该 代 码 段 是 从 数 据 库 中 加 载 路 由 的 核 心 实 现 。

localteRoutefromDB ( ) 方 法 从 数 据 库 中 加 载 路 由 , 返 回RouteDefinitionVo数学模型的数据库路由器列表信息。上面是该数学模型类的代码:

transfer( ) 方 法 实 现 了 从 RouteDefinitionVo 到RouteDefinition的类型转换,上面是transfer()方法调用的类型转换的核心理念代码:

说明5#:在代码段中,

GatewayPredicateDefinitionFactory完成断言的模式相匹配转换。Predicate-Definition是断言的数学模型定义,定义name为Key、args为Value。举例如下:

GatewayPredicateDefinitionFactory完成冷却系统的模式相匹配转换。FilterDefinition是冷却系统的数学模型定义,定义name为Key、args为Value。举例如下:

Spring Cloud Gateway源代码导出

启动Spring Cloud Gateway,需要依赖非官方的Starter模块。上面我们从Maven依赖开始,对Spring Cloud Gateway的源代码进行导出。

初始化加载

上述是

spring-cloud-starter-gateway启动前需要引用的一个自动配置Starter,能透过查询该Starter的源代码发现Spring CloudGateway的同时实现所依赖的模块,Maven配置

可 以 看 到 Spring Cloud Gateway 的 Starter 启 动 类 主 要 依 赖spring-cloud-gateway-core模块。采用EnableAutoConfiguration注解完成自动配置初始化信息,我们在Spring Cloud Gateway下的spring.factories(在包spring-cloud-gateway-core)声明文件如下:

GatewayAutoConfiguration

说明:

GatewayAutoConfiguration配置是Spring Cloud Gateway的核心理念配置类,初始化如下模块:

NettyConfiguration

GlobalFilter(

AdaptCachedBodyGlobalFilter、RouteToRequestUrlFilter、 ForwardRoutingFilter、ForwardPathFilter、WebsocketRoutingFilter、WeightCalculatorWebFilter等)

FilteringWebHandler

GatewayProperties

PrefixPathGatewayFilterFactory

RoutePredicateFactory

RouteDefinitionLocator● RouteLocator

RoutePredicateHandlerMapping(查找相匹配到的Route并进行处置)

GatewayWebfluxEndpoint(管理交换机的HTTP API)

HTTP允诺路由器源代码分析

Spring Cloud Gateway中采用HandlerMapping对允诺的链接进行导出,相匹配相关联的Route,转发到相关联的服务工程项目。下图为整个允诺的流程 , 用 户 请 求 先 通 过 DispatcherHandler 找 到 对 应 的GatewayHandlerMapping,再透过GatewayHandlerMapping导出相匹配到的Handler;Handler处置完后,经过Filter处置,最终将允诺转发到后端服务工程项目。

在前面的静态路由器加载过程中,其实已经贯穿了整个HTTP允诺的调用链路,具体如下:

允诺先由DispatcherHandler进行处置,DispatcherHandler在初始化时会在Spring IoC罐子中查找同时实现HandlerMapping接口的同时实现类 。然 后 保 存 到 内 部 变 量 handlerMappings 数 据 结 构 中 。

DispatcherHandler 调 用 handler 方 法 迭 代 handlerMappings 中 的HandlerMapping接口,主要源代码

AbstractHandlerMapping 在 getHandler 方 法 中 封 装 了CORS(Cross-Origin Resource Sharing,跨域天然资源共享)。因为所有Handler都可能涉及CORS的处置,所以抽象类AbstractHandlerMapping提供了getHandlerInternal子类来同时实现查找Handler的具体方法。

RoutePredicateHandlerMapping用于相匹配具体的路由器,并返回FilteringWebHandler 。通 过 RoutePredicateHandlerMapping 中 的RouteLocator 对 象 存 储 启 动 时 加 载 的 路 由 对 象 信 息 。当RoutePredicateHandlerMapping获取相关联的路由器时,会将Route信息存储到ServerWebExchanges特性中,然后返回同时实现了WebHandler接口的FilteringWebHandler 。FilteringWebHandler 是 一 个 存 放 过 滤 器 的Handler。

调用RoutePredicateHandlerMapping的getHandlerInternal方法从RouteLocator获取路由器,并存放在ServerWebExchange中,返回webFilter对象,

DispatcherHandler 通 过 SimpleHandlerAdapter 组 件 调 用FilteringWebHandler模块的handler方法,FilteringWebHandler模块接 着 调 用 之 前 在 容 器 中 注 册 的 所 有 Filter , 处 理 完 毕 后 返 回Response,

小结

构筑积极响应式微服务工程项目能获得触发器、积极响应性、弹性、快速恢复、背压等系统优点,同时积极响应式微服务工程项目架构在天然资源挤占、高mammalian、高吞吐、触发器处置情景中具有更强的优势。目前积极响应式架构技术选型众多,如果将积极响应式程式设计应用到大规模生产系统中,则需要进行周密的调研,并对实际工程项目周期、人员经验、技术架构等因素进行综合权衡考虑,避免技术的复杂度难题成为业务发展过程中的瓶颈。

1.本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2.分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3.不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4.本站提供的源码、模板、插件等其他资源,都不包含技术服务请大家谅解!
5.如有链接无法下载或失效,请联系管理员处理!
6.本站资源售价只是赞助,收取费用仅维持本站的日常运营所需!