gateWay技术文档分析
- 引言
1.1 背景和动机
项目的主体架构为 LB(Nginx) + 网关gateWay)java应用。故gateWay 框架技术应用较多,通过此篇文档梳理网关技术及应用原理。
1.2 文档目的
作者梳理gateWay技术及为后续入职小伙伴,在等待开发设备(电脑)期间提供知识的整理唤起,及在遇到与gateWay相关的问题时能更快地进行定位和分析问题原因,并能结合知识进行问题的分析和解决方案的制定为目的。
1.3 受众
java开发相关人员。
1.4 课题范围
gateWay 启动流程及请求处理流程,以及其中组合框架。
1.5 术语和定义
- 技术概述
Spring Cloud gateWay 是由 WebFlux + Netty + Reactor 实现的响应式的 API 网关。
2.1 技术架构概述
+---------------------------------------------------+
| gateWay Server |
| |
| +--------------------------+ |
| | Route Locator | |
| +--------------------------+ |
| | |
| +--------------v--------------+ |
| | Route Definitions | |
| | (Configured Routes) | |
| +--------------|--------------+ |
| | |
| +--------------v--------------+ |
| | Web Handler | |
| | (Request Handling Logic) | |
| +--------------|--------------+ |
| | |
| +--------------v--------------+ |
| | Filters and Interceptors| |
| | (Pre, Post, Route Filters) | |
| +---------------------------+ |
| |
+---------------------------------------------------+
2.2 关键组件
gateWay Server: Spring Cloud gateWay 的主要服务器,负责接收并处理客户端的请求。
Route Locator: 用于定位路由的组件,负责获取配置的路由信息。
Route Definitions: 存储配置的路由定义,指定了请求应该如何被路由和处理。
Web Handler: 处理请求的核心组件,包含请求处理逻辑。根据路由定义,它选择适当的处理方式。
Filters and Interceptors: 用于实施过滤器和拦截器的组件。过滤器用于在请求到达目标服务之前或响应返回客户端之前执行操作。拦截器则可以执行全局的前置和后置处理。
2.1 技术架构概述中简化的架构图展示了 Spring Cloud gateWay 的基本组件及其交互。实际上,Spring Cloud gateWay 的架构可以更复杂,可以包括一些其他的组件和服务,例如负载均衡、熔断器等,具体取决于你的应用场景和配置。架构图可以根据实际情况进行扩展和详细设计。
2.3 工作流程
官网流程图比较简单可以自行查看,下面为个人具体化的流程图:
3. 关键技术原理
3.1 技术 gateWay Server/gateWay-start
其中gateWay-start 没有什么东西可说,就是一些必要jar的集合。
3.1.1 核心组件
通过Start 包找到对应核心源码项目:
3.1.2 原理概述
1.根据spring Boot的启动流程来看,在自动装配中的文件位置找到如下:
2.分析
得到如下结论:
在项目中包含DisptcherHandler类存在的情况下进行自动配置。
在自动配置前gateWay所做:HttpHandler,WebFlux后,LB负责配置及日志打印。
3.去配置yaml或文件中去创建,前提是没有PropertiesRouteDefinitionLocator对象时。
3.1 PropertiesRouteDefinitionLocator 对象中获取得到 RouteDefinition对象
到这里就完成自动配置功能,在说明白一些就是路由的装配完成了。
附:具体yaml配置中的属性
3.1.3 数据流程
上面说了yaml配置文件读取原理,本节就说一下具体的gateWay接受数据及处理数据的流程及原理。
通过上面章节得知应用gateWay框架必须用到webflux框架,先简单说一下webflux,它是spring-framework核心包下的web项目,Spring WebFlux :: Spring Framework 官网有具体介绍,这里就不重复了。
值得一提是,在处理web请求时,通常有两种体系结构,分别为:thread-based architecture(基于线程)、event-driven architecture(事件驱动)
线程:
事件:
到处简单介绍WebFlux完毕!
继续来看gateWay的数据流向,先上图,图中摒弃掉了webFlux DispatchHandler操作部分。
下面根据流程图及源码分析具体数据流向。
1⃣️RoutePredicateHandlerMapping 中的路程(谓词)
圈 1⃣️中lookupRoute 方法获取具体路由地址,下面分析一下lookupRoute方法。
圈1⃣️中的getRoutes方法获取我们yaml中配置的路由集合,圈2⃣️是遍历获取RoutesList与请求数据进行对比匹配。
通过调试源码发现,如果不说一下DispatchHandler 这个类,无法继续获取Filter相关的类型,导致文档逻辑不清楚,这里就补充一下吧。
先上图,在哪个包中去找:
在sprig-webFlux包中,DispatchHandler类中的 handle方中4⃣️是此方法的重点,mapping.getHandle 就是上面提到的获取 RoutePredicateHandlerMapping的入口,这次根源就找到了。
继续对接下面的技术点gateWayFilter怎么得到?看上图invokeHandler方法就是根据这个方法得到,具体看方法的调用链,先上图:
handle是个接口方法,具体的由子类实现,为什么是Simple..Adapter 这个适配器呢?是调试得来的。
具体的方法体,值得一提,直接强转类型。
进入WebHandler中看一下,发现handle是个接口方法,具体调试发现,实现是FilteringWebHandler类,现在一看很清楚了Filter也明朗了,进一步跟进handle的实现方法。
这下清晰可见了globale全局的,gateWay的默认的都在了,默认的这里就省略了,可以看具体的上面提供的spring官网文档中默认过滤器。
这里需要注意的,是上面说的Filter是个前置过滤器,即数据没有到达具体Node服务,前置处理完毕,到达Node服务自己的业务逻辑,返回处理后的数据。后续还在DispatchHandler中 handleResult(exchange, result)方法中处理,对返回数据过滤处理,这里就简单的说一下,贴一张图。
总结:分析到这里基本的gateWay的功能就说完了,所涉及到的概念就是 谓语,过滤,路由原理及流程说完了。
4. 技术整合
4.1.1整合负载均衡技术
上面图可以得知LB负载gateWay本身支持,并且可以配置在yaml中。通Filter的方式介入到gateWay框架中的。具体的体现在uri:lb://system-server
4.1.2 自定义负载策略
1⃣️实现具体图中接口即可。
2⃣️具体的可以参考下面案例
4.2 熔断介入(后续补上)
5. 性能
5.1 性能优势
解读一下:
Avg Req/Sec/Thread=3.24k 的意思是每个线程平均处理大约 3,240 个请求每秒。
Avg Latency = 6.61ms 表示平均延迟为 6.61 毫秒。这是一个描述系统响应时间的性能指标。在性能测试中, 表示系统处理请求所需的平均时间。
2⃣️非阻塞式异步编程模型:Spring Cloud gateWay 是基于 Spring WebFlux 框架构建的,使用了 Reactive Stream 的异步编程模型,能够提供更高的并发能力和更低的延迟。基于路由的请求处理:Spring Cloud gateWay 的核心功能是基于路由的请求处理,能够将不同的请求路由到不同的后端服务上,并提供丰富的路由配置选项。高度可扩展:Spring Cloud gateWay 提供了丰富的扩展点和插件机制,可以自定义路由、请求转发、限流等功能。
5.2 性能劣势
1⃣️学习成本高:Spring Cloud gateWay 采用了基于函数式编程的 Reactive Stream 异步编程模型,需要对相关概念、框架和 API 有一定的理解和掌握才能使用和定制。性能瓶颈:Spring Cloud gateWay 的性能瓶颈主要集中在 CPU 和内存上,处理高并发请求时需要保证机器资源充足。无法完全替代传统 API 网关:Spring Cloud gateWay 虽然提供了基于路由的请求处理能力,但无法完全替代传统的 API 网关,如 Nginx 和 Kong 等,因为一些传统 API 网关的功能,如高级的负载均衡、缓存和安全性等,还未完全支持。
2⃣️业务量达到一定量级后性能不足。(重点)
上面的1⃣️中提到了,它无法代替传统的网关。因为它是基于JVM容器机制,受JVM内存大小,GC,线程状态等限制。
举个上面源码中的例子,也是官网提出建议性说明的地方。
匹配路由:
从上面查找路由的方法中,我们就可以发现其性能瓶颈在逐条遍历上,如果当前有几千个API,可能看不出性能差距,当有上万条API时,该方法的性能可能会大幅度降低。虽然用了流式处理,但是抛去遍历的时间复杂度 O(n) ,同时还要去每个路由内去做条件过滤,才能找到符合条件的路由返回,进行下一步操作。这样即使我们有更高的内存以及性能更好的CPU也没办法发挥出其硬件的实力。因为从根本上,Spring Cloud gateWay的路由策略就限制了瓶颈。
6.安全性
6.1 日常安全
在构建网关时,需要防范各种攻击,例如:SQL注入、跨站脚本攻击、拒绝服务攻击等。为了防范这些攻击,需要采取以下几个措施:
输入验证:对于所有的输入参数进行验证,确保输入的数据不会包含恶意代码或攻击代码。
对称与非对称:对于敏感的数据,需要使用加密算法进行加密,以防止被攻击者窃取。
限流和速率控制:对于某些请求频率比较高的接口,需要进行限流和速率控制,以防止被攻击者进行拒绝。
服务隔离:将不同的服务隔离开来,以防止某个服务被攻击后,影响到整个系统的运行。
7. 部署和维护
7.1 部署流程
开发阶段 :在开发者使用Maven或Gradle构建环境配置项目的相关依赖和代码。确保你的应用已经满足所有必要的条件并能够正常运行。同时,你还需要为应用程序编写一些测试用例以确保其功能正常且稳定运行。这里以Maven为例子前提是你用SpringBook+Spring Cloud,看下图:
集成测试与系统测试 : 在开发和单元测试之后,你需要对整个系统的各个部分(包括前端、后端以及数据库)执行全面的集成测试和工作负载压力测试来确认一切工作正常并能适应生产环境的挑战。这是验证产品质量的关键一步。这部分可以通过JUnit等工具来完成。
容器化与发布到云平台(例如: Kubernetes) :当你完成了上述的本地开发流程并在性能和质量上满足了要求之后,就可以考虑将其推送到远程环境中了,特别提醒一定要确定版本号。一般来说这个过程由专门的团队负责处理,他们将把打包好的Docker镜像或者Kubernetes模板上传到一个可以提供服务的公共云平台上。这通常会涉及到持续交付/持续部署 (CD/CD) 策略的实现和使用。
7.2 系统配置
根据实际情况配置gateWay分为yaml及数据的动态,下面只是列出基本yaml配置及常见优化配置:
有注册中心的基本配置:
spring:
application:
name: gateWay
cloud:
nacos: #使用注册中心
config:
server-addr: ${spring.cloud.nacos.discovery.server-addr}
discovery:
server-addr: 127.0.0.1:8848
gateWay:
routes:
- id: web-user # 唯一就行请求 http://localhost:9999/user/info 会转发到web-user 服务
uri: lb://web-user #有集群的情况下(一般有注册中心就用lb)在服务注册中心找服务名为 zhufeng-web-user 的服务
predicates:
- Path=/user/info # 设置路由断言,当请求 /user/info 时进行转发
- id: web-msg # 请求 http://localhost:9999/route/msg/info 会转发到 web-msg 服务
uri: lb://web-msg
predicates:
- Path=/route/msg/info # 设置路由断言,当请求 /msg/info 时进行转发
filters:
- StripPrefix=1 # 前缀, 在当前路径匹配中表示去掉第一个前缀 /route
限流的基本配置以redis为主,熔断的配置hystrix:
1⃣️yaml配置
spring:
application:
name: gateWay
cloud:
gateWay:
routes:
- id: 5i5j-SSO
uri: lb://5i5j-SSO
predicates:
- Path=/sso/**
filters:
- StripPrefix=1
- name: Hystrix #熔断
args:
name: defaultfallback
fallbackUri: forward:/defaultfallback
- name: RequestRateLimiter #请求数限流,名字不能乱打
args:
key-resolver: "#{@ipKeyResolver}"
redis-rate-limiter.replenishRate: 1 #生成令牌速率-设为1方便测试
redis-rate-limiter.burstCapacity: 1 #令牌桶容量-设置1方便测试
redis:
database: 0
cluster:
nodes: x.x.x.x:18003,x.x.x.x:18004,x.x.x.x:99005,x.x.x.x:99003,x.x.x.x:17004
password: XXXXX #密码
timeout: 6000ms #连接超时时长(毫秒)
jedis:
pool:
max-active: -1 #连接池最大连接数(使用负值表示无极限)
max-wait: -1ms #连接池最大阻塞等待时间(使用负值表示没有限制)
max-idle: 10 #连接池最大空闲连接
min-idle: 5 #连接池最小空间连接
2⃣️自建配置类,书写限流规则如图:
有熔断的类:
7.3 监控和日志
监控上一般都有注册中心来进行心跳检测,不必担心。但是防止项目有特殊情况,可以在yaml中设置服务为非临时实例:
日志方面,主要是快速定位及重要业务流程的输出的作用。针对运行时异常,它提供全局过滤。可以动态返回具体类型的错误提示。实现也很简单重ErrorWebExceptionHandler类就可以了。
7.4 优化项配置说明
1⃣️全局的Http超时设置
httpclient:
connect-timeout:
response-timeout:
2⃣️全局跨域配置一般是写在代码中,减少yaml文件读取的IO的性能消耗。
8. 总结
在实际应用中,开发者可能遇到各种各样的开发问题,生产问题。以上只是简要概括了本人在gateWay的各个环节的主要目标的知识点,高门槛的知识如底层的Netty,Reactor,web- Flux等没有涉及到,但是本篇文档的目的,在遇到与gateWay相关的问题时能更快地进行定位和分析问题原因,并能结合知识进行问题的分析和解决方案的制定,这有助于你在工作中更好地解决问题和处理异常情况。
9.差异
发现有些项目中用到的是zuul框架,作为统一网关,下面就简单说一下它们的不同之处。spring-cloud-Gateway是spring-cloud的一个子项目。而zuul则是netflix公司的项目,只是spring将zuul集成在spring-cloud中使用而已。
因为zuul2.0连续跳票和zuul1的性能表现不是很理想,所以催生了spring团队开发了Gateway项目。
Zuul:使用的是阻塞式的 API,不支持长连接,比如 websockets;底层是servlet,Zuul处理的是http请求,没有提供异步支持,流控等均由hystrix支持;依赖包spring-cloud-starter-netflix-zuul。
Gateway:Spring Boot和Spring Webflux提供的Netty底层环境,不能和传统的Servlet容器一起使用,也不能打包成一个WAR包。依赖spring-boot-starter-webflux和/ spring-cloud-starter-gateway提供了异步支持,提供了抽象负载均衡,提供了抽象流控,并默认实现了RedisRateLimiter。
相同点:底层都是Servlet;两者都是web次面的网关框架,处理的是Http请求。
不同点:
1⃣️设计角度
上面也提到了,两个框架的厂商的不同,netflix为SpringCloud系列提供了早期的原理及思想,但是有些方面还是有不足之处的。Spring在它的基础上进行了各方面的优化。
2⃣️性能
WebFlux 模块的名称是 spring-webflux,名称中的 Flux 来源于 Reactor 中的类 Flux。Spring webflux 有一个全新的非堵塞的函数式 Reactive Web 框架,可以用来构建异步的、非堵塞的、事件驱动的服务,在伸缩性方面表现非常好。使用非阻塞API。 Websockets得到支持,并且由于它与Spring紧密集成,所以将会是一个更好的 开发 体验。
Zuul 1.x,是一个基于阻塞io的API Gateway。Zuul已经发布了Zuul 2.x,基于Netty,也是非阻塞的,支持长连接,但Spring Cloud暂时还没有整合计划。
3⃣️组件
gateway对比zuul多依赖了spring-webflux,在spring的支持下,功能更强大,内部实现了限流、负载均衡等,扩展性也更强,但同时也限制了仅适合于Spring Cloud套件。zuul则可以扩展至其他微服务框架中,其内部没有实现限流、负载均衡等。