目录
spring-cloud-gateway 和zuul
spring webflux 和 spring mvc
spring-cloud-gateway 的两种模式
spring-cloud-gateway server 模式下配置说明
grayLb://system-server 灰度发布代码实现
spring-cloud-gateway 和zuul
zuul 是spring全家桶的第一代网关组件, 基于同步线程Servlet API,在高并发场景下表现不如Gateway;spring-cloud-gateway 提供了基于WebFlux的非阻塞编程模型(也支持servlet),Gateway可以处理更多的并发请求,具有高性能、高吞吐量和低延迟的优势。
所以老的遗留系统还会有zuul, 新系统一般都会选择 spring-cloud-gateway 的webflux 。
spring webflux 和 spring mvc
spring 提供了两套web方案
spring mvc : 基于servlet 和 web 容器(tomcat) , servlet 又是基于阻塞线程的,可以简单理解为一个请求分配一个线程,这个线程就只负责处理这个请求,tomcat jdbc 、spring 事务等其他核心组件也是基于阻塞线程的,他们可以很好搭配使用 。
webflux :
WebFlux使用非阻塞、事件驱动的模型,这意味着少量线程可以处理大量请求,请求和线程不是一对一的关系。在WebFlux中,由于采用了非阻塞的编程模型,一个业务的不同步骤甚至可能在不同的线程中执行。这就导致了传统JDBC模型中的事务管理在WebFlux环境下会出现问题。其他很多基于线程的组件都不能用,整个生态还不成熟,所以webflux虽然性能好,所以迟迟没有被广泛适用,但可以用在有限的场景下,比如网关。
spring-cloud-gateway 的两种模式
server 模式 : 内置了完善的网关需要的核心功能,比如请求转发、过滤拦截、限流等。
Proxy Exchange: 作为一个你的程序中的一个组件,抓发请求到下游服务器,就当成httpClient等工具使用。
这两种模式都有webflux 和 springmvc 这两种实现。
spring-cloud-gateway server 模式下配置说明
cloud:
# Spring Cloud Gateway 配置项,对应 GatewayProperties 类
gateway:
# 路由配置项,对应 RouteDefinition 数组
routes:
## system-server 服务
- id: system-admin-api # 路由的编号
uri: grayLb://system-server
predicates: # 断言,作为路由的匹配条件,对应 RouteDefinition 数组
- Path=/admin-api/system/**
filters:
- RewritePath=/admin-api/system/v3/api-docs, /v3/api-docs # 配置,保证转发到 /v3/api-docs
id: 路由位置标识,用于区分各条路由
uri: 下游目标服务的地址 ,grayLb://system-server , 这里可以是常规的schema. http 和 https,也可以是springcloud内置的lb , 也可以自定义,然后在filter里面实现,这里grayLb就是自定义的灰度发版,具体实现逻辑下一章介绍。
predicates : 配置这条路由的条件,满足这个条件,触发这条路由
filters: 这条路由的过滤器(局部过滤器,springcloud-gateway分全局过滤器和局部过滤器两大类), 上面的例子是路径重写过滤器,就是转发到下游时候将
/admin-api/system/v3/api-docs 改成 /v3/api-docs
grayLb://system-server 灰度发布代码实现
gateway ,会将下游服务器配置+用户请求的uri简单拼接,放到属性GATEWAY_REQUEST_URL_ATTR 中, GrayReactiveLoadBalancerClientFilter 第一步拿到schema ,如果发现不是grayLb , 则跳过该过滤器,直接执行其他过滤器 ,过滤器是责任链模式实现的。
如果是grayLb ,则执行灰度逻辑:将grayLb://system-server 换成某一台具体的机器。
具体灰度逻辑:
这里的灰度逻辑比较简单,就是请求加了一个version的请求头,然后后端服务注册到注册中心时候在注册信息的metadata中写了一个version , 前端请求只会发到与后端version匹配的的server上。
发散思考:请求头什么时候加进去?
1.前端代码直接加,适用于前端多版本共存的情况,比如前端是andriod apk,那么前端多个版本共存就很常见了。
2.后端直接加,比如前端只有web,那么前端一般都是最新版本,这时候我们要做灰度,就可以直接在GrayLoadBalancer灰度了,实现逻辑不用version header头了,可以加一个配置,灰度比例 ,假设10% 进行灰度,那么选择一个灰度因子,比如请求客户端IP,请求到达时间,用户等级、用户年龄等,然后将该因子的10%转发到灰度版本上。