【SpringCloud 技术专题】「Gateway 网关系列」(1)微服务网关服务的 Gateway 组件的原理介绍分析
为什么要有服务网关?
我们都知道在微服务架构中,系统会被拆分为很多个微服务。那么作为客户端要如何去调用这么多的微服务呢?难道要一个个的去调用吗?很显然这是不太实际的,我们需要有一个统一的接口与这些微服务打交道,这就是我们需要服务网关的原因。
我们已经知道,在微服务架构中,不同的微服务可以有不同的网络地址,各个微服务之间通过互相调用完成用户请求,客户端可能通过调用 N 个微服务的接口完成一个用户请求。比如:用户查看一个商品的信息,它可能包含商品基本信息、价格信息、评论信息、折扣信息、库存信息等等,而这些信息获取则来源于不同的微服务,诸如产品系统、价格系统、评论系统、促销系统、库存系统等等,那么要完成用户信息查看则需要调用多个微服务,这样会带来几个问题:
客户端多次请求不同的微服务,增加客户端代码或配置编写的复杂性认证繁杂,访问每个服务都要进行一次认证每个服务都通过 http 访问,导致 http 请求增加,效率不高拖慢系统性能多个服务存在跨域请求问题,处理起来比较复杂
我们该如何解决这些问题呢?我们可以尝试想一下,不要让前端直接知道后台诸多微服务的存在,我们的系统本身就是从业务领域的层次上进行划分,形成多个微服务,这是后台的处理方式。对于前台而言,后台应该仍然类似于单体应用一样,一次请求即可,于是我们可以在客户端和服务端之间增加一个 API 网关,所有的外部请求先通过这个微服务网关。它只需跟网关进行交互,而由网关进行各个微服务的调用。
这样的话,我们就可以解决上面提到的问题,同时开发就可以得到相应的简化,还可以有如下优点:
减少客户端与微服务之间的调用次数,提高效率便于监控,可在网关中监控数据,可以做统一切面任务处理便于认证,只需要在网关进行认证即可,无需每个微服务都进行认证降低客户端调用服务端的复杂度这里可以联想到一个概念,面向对象设计中的门面模式,即对客户端隐藏细节,API 网关也是类似的东西,只不过叫法不同而已。它是系统的入口,封装了应用程序的内部结构,为客户端提供统一服务,一些与业务本身功能无关的公共逻辑可以在这里实现,诸如认证、鉴权、监控、缓存、负载均衡、流量管控、路由转发等等。示意图
SpringCloud Gateway 网关介绍
SpringCloud Gateway 是 Spring Cloud 的一个全新项目,该项目是基于 Spring 5.0,Spring Boot 2.0 和 Project Reactor 等技术开发的网关,它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式。
SpringCloud Gateway 作为 Spring Cloud 生态系统中的网关,目标是替代 Zuul,在 Spring Cloud 2.0 以上版本中,没有对新版本的 Zuul 2.0 以上最新高性能版本进行集成,仍然还是使用的 Zuul 2.0 之前的非 Reactor 模式的老版本。而为了提升网关的性能,SpringCloud Gateway 是基于 WebFlux 框架实现的,而 WebFlux 框架底层则使用了高性能的 Reactor 模式通信框架 Netty。
总结一下,服务网关大概就是四个功能:统一接入、流量管控、协议适配、安全维护。而在目前的网关解决方案里,有 Nginx+ Lua、Spring Cloud Zuul 以及 Spring Cloud Gateway 等等。这里以 Spring Cloud Gateway 为例进行说明。
Spring Cloud Gateway 的目标,不仅提供统一的路由方式,并且基于 Filter 链的方式提供了网关基本的功能,例如:安全,监控/指标,和限流。
提前声明:Spring Cloud Gateway 底层使用了高性能的通信框架 Netty。
SpringCloud Gateway 特征
SpringCloud 官方,对 SpringCloud Gateway 特征介绍如下:
基于 Spring Framework 5,Project Reactor 和 Spring Boot 2.0
集成 Hystrix 断路器
集成 Spring Cloud DiscoveryClient
Predicates 和 Filters 作用于特定路由,易于编写的 Predicates 和 Filters
具备一些网关的高级功能:动态路由、限流、路径重写
从以上的特征来说,和 Zuul 的特征差别不大,SpringCloud Gateway 和 Zuul 主要的区别,还是在底层的通信框架上。
简单说明一下上文中的三个术语:
Filter(过滤器):
和 Zuul 的过滤器在概念上类似,可以使用它拦截和修改请求,并且对上游的响应,进行二次处理。
过滤器为 org.springframework.cloud.gateway.filter.GatewayFilter 类的实例。
Route(路由):
网关配置的基本组成模块,和 Zuul 的路由配置模块类似。
一个 Route 模块由一个 ID,一个目标 URI,一组断言和一组过滤器定义。如果断言为真,则路由匹配,目标 URI 会被访问。
Predicate(断言):
一个 Java 8 的 Predicate,可以使用它来匹配来自 HTTP 请求的任何内容,例如 headers 或参数。断言的输入类型是一个 ServerWebExchange。
SpringCloud Gateway 的核心架构
迎来了 Webflux,Webflux 的出现填补了 Spring 在响应式编程上的空白,Webflux 的响应式编程不仅仅是编程风格的改变,而且对于一系列的著名框架,都提供了响应式访问的开发包,比如 Netty、Redis 等等。
SpringCloud Gateway 使用的 Webflux 中的 reactor-netty 响应式编程组件,底层使用了 Netty 通讯框架。
SpringCloud Zuul 的核心架构
SpringCloud Zuul 的 IO 模型
Springcloud 中所集成的 Zuul 版本,采用的是 Tomcat 容器,使用的是传统的 Servlet IO 处理模型。
servlet 由 servlet container 进行生命周期管理。
container 启动时构造 servlet 对象并调用 servlet init()进行初始化;
container 关闭时调用 servlet destory()销毁 servlet;
container 运行时接受请求,并为每个请求分配一个线程(一般从线程池中获取空闲线程)然后调用 service()。
Servlet 的 IO 模型
servlet 是一个简单的网络 IO 模型,当请求进入 servlet container 时,servlet container 就会为其绑定一个线程,在并发不高的场景下这种模型是适用的,但是一旦并发上升,线程数量就会上涨,而线程资源代价是昂贵的(上线文切换,内存消耗大)严重影响请求的处理时间。
在一些简单的业务场景下,不希望为每个 request 分配一个线程,只需要 1 个或几个线程就能应对极大并发的请求,这种业务场景下 servlet 模型没有优势。
Springcloud Zuul 是基于 servlet 之上的一个阻塞式处理模型,即 spring 实现了处理所有 request 请求的一个 servlet(DispatcherServlet),并由该 servlet 阻塞式处理处理。
Springcloud Zuul 无法摆脱 servlet 模型的弊端,虽然 Zuul 2.0 开始,使用了 Netty,并且已经有了大规模 Zuul 2.0 集群部署的成熟案例,但是,Springcloud 官方已经没有集成改版本的计划了。
Webflux 服务器
Webflux 模式替换了旧的 Servlet 线程模型,用少量的线程处理 request 和 response io 操作,这些线程称为 Loop 线程,而业务交给响应式编程框架处理,响应式编程是非常灵活的,用户可以将业务中阻塞的操作提交到响应式框架的 work 线程中执行,而不阻塞的操作依然可以在 Loop 线程中进行处理,大大提高了 Loop 线程的利用率。官方结构图:
Webflux 虽然可以兼容多个底层的通信框架,但是一般情况下,底层使用的还是 Netty,Netty 是目前业界认可的最高性能的通信框架。
而 Webflux 的 Loop 线程,正好就是著名的 Reactor 模式 IO 处理模型的 Reactor 线程,如果使用的是高性能的通信框架 Netty,这就是 Netty 的 EventLoop 线程。
Spring Cloud Gateway 的处理流程
GatewayClassPathWarningAutoConfiguration 作用检查是否配置我们 webflux 依赖。
GatewayAutoConfiguration 加载了我们 Gateway 需要注入的类。
GatewayLoadBalancerClientAutoConfiguration 网关需要使用的负载均衡,Lb//jarye-member// 根据服务名称查找真实地址
GatewayRedisAutoConfiguration 网关整合 Redis 整合 Lua 实现限流
GatewayDiscoveryClientAutoConfiguration 服务注册与发现功能
客户端向网关发送 Http 请求,会到达 DispatcherHandler 接受请求,匹配到 RoutePredicateHandlerMapping。
根据 RoutePredicateHandlerMapping 匹配到具体的路由策略。
FilteringWebHandler 获取的路由的 GatewayFilter 数组,创建 GatewayFilterChain 处理过滤请求
执行我们的代理业务逻辑访问。
Spring Cloud Gateway 的源码流程
过滤器默认有 8 种,采用责任链模式关联着:
SpringCloud Gateway 官方资源
源码及案例
https://github.com/spring-cloud/spring-cloud-gateway
https://github.com/spring-cloud/spring-cloud-gateway/blob/main/spring-cloud-gateway-sample/pom.xml
案例
https://spring.io/projects/spring-cloud-gateway#samples
版权声明: 本文为 InfoQ 作者【浩宇天尚】的原创文章。
原文链接:【http://xie.infoq.cn/article/e9cf14346340f8dddaaac3f92】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论