Open aCoder2013 opened 5 years ago
请问大神最后用了什么方案来做网关
请问spring gateway 有http 1.0下,性能是不是很差?
@mingletxt https://github.com/spring-cloud/spring-cloud-gateway/issues/301 这里有个测试可以参考下
@mingletxt 我最后采取的是spring 4.x + Spring boot 1.5.x的方案,基于servlet3.1的异步,因为我们内部很多插件还不支持spring boot2.x,后续会迁移到spring webflux的方案
背景
目前的网关是基于
Spring Boot 1.5.x
和Tomcat 8.5.x
构建,采用多线程阻塞模型,也就是说每个请求都会占用一个独立的线程资源,而线程在JVM中是一个相对比较重的资源。当应用是CPU密集型的或者说依赖的远程服务都正常工作时,这种模型能够很好的满足需求,但一旦后端服务出现了延迟,比如慢查询、FullGC、依赖的第三方接口出问题等情况,线程池很容易被打满,使得整个集群服务出现问题。典型的IO密集型的应用也会有类似的问题,比如网关有很多HTTP请求、RPC远程调用等,当并发量比较大的时候,线程都阻塞在IO等待上,造成线程资源的浪费。这种模型的优势比较明显:
但劣势也很明显:
而异步化的方式则完全不同,通常情况下一个CPU核启动一个线程即可处理所有的请求、响应。一个请求的生命周期不再固定于一个线程,而是会分成不同的阶段交由不同的线程池处理,系统的资源能够得到更充分的利用。而且因为线程不再被某一个连接独占,一个连接所占用的系统资源也会低得多,只是一个文件描述符加上几个监听器,而在阻塞模型中,每条连接都会独占一个线程,是一个非常重的资源。对于上游服务的延迟情况,能够得到很大的缓解,因为在阻塞模型中,慢请求会独占一个线程资源,而异步化之后,因为单条连接诶所占用的资源变的非常低,因此系统可以同时处理大量的请求。
因此考虑对网关进行异步化改造,解决当前遇到的超时、延迟等问题。
技术选型
Zuul 2
Zuul 2基于Netty和RxJava实现,采用了异步非阻塞模型,本质上其实就是队列+事件驱动。在zuul 1中一个请求的完整生命周期都是在一个线程中完成的,但在zuul 2中,请求首先会经过netty server,接着会运行前置拦截器,然后通过netty客户端将请求转发给后端的服务,最后运行后置拦截器并返回响应。但是和zuul 1不同,这里的拦截器同时支持异步和同步两种模式,对于一些比较快的操作,可以直接使用同步拦截器。
异步拦截器示例:
这里返回的是一个
Observable
,这是RxJava
中的概念,和Java8的CompletableFuture
有点像,对于方法调用者来说拿到的都是一个Observable
,而内部的实现方式可以是同步,也可以是异步,但是调用者不用关心这个东西,无论实现怎么改,方法的签名是不用变的,始终返回的都是一个Observable
。Zuul 2是一个不错的选择,但是spring官方已经不打算集成zuul 2了,加上Netflix也打算把技术栈尽可能的迁移到Spring,hystrix和Eureka也都进入维护状态,不再开发新特性,zuul未来也有可能是同样的命运。
基于Servlet3.1的异步
Servlet3.1引入了非阻塞式编程模型,支持请求的异步处理。
Spring 4.x+
也增加了对非阻塞式IO的支持,例如下面的代码示例(SpringMVC5 + Tomcat 8.5+):虽然说Servlet3.1提供了对异步的支持,但是其编程模型本质上还是同步的:
Filter
,Servlet
, 或者有一些方法仍然是阻塞的,比如getParameter
,getPart
等,解析请求体、写会响应本质上还是同步的,但一般来说性能损耗也不算大,网关的耗时基本上都在业务方的IO调用上。Spring 5 Reactive
对于异步编程模型的选择,Spring5中引入了两种方式,一种是构建于Servlet 3.1之上的
SpringMVC
,另一种是构建于Netty之上的Spring WebFlux
。Spring WebFlux
不同于Spring MVC
,是一个专门为异步设计的响应式框架,完全非阻塞,支持响应式编程模型,可以运行在 Netty, Undertow, 和 Servlet 3.1+容器中。不同于SpringMVC,WebFlux的请求体、响应都支持响应式类型,可以异步的接受、写入响应,是一个完全异步化的框架。
另外
Spring WebFlux
也提供了一个响应式、非阻塞的HTTP客户端:WebClient
. 其内部支持多种实现,默认是Reactor Netty
,也支持Jetty reactive HttpClient,当然也可以自己通过ClientHttpConnector
扩展。Spring Cloud Gateway
Spring Cloud Gateway是由spring官方基于Spring5.0、Spring Boot2.0、Project Reactor等技术开发的网关,目的是代替原先版本中的Spring Cloud Netfilx Zuul,目前Netfilx已经开源了Zuul2.0,但Spring没有考虑集成,而是推出了自己开发的Spring Cloud GateWay。该项目提供了一个构建在Spring生态系统之上的API网关。 特性:
Spring Cloud DiscoveryClient
自研
另外也可以参考Zuul2、Spring Cloud Gateway等,基于Netty、Vertx或者spring4.x提供的基于Servlet 3.1的异步机制自研,但自研成本会很高,需要从零开始开发。
对比
问题
需要特别注意的一些问题:
总结
网关的异步化改造相对还是比较必要的,作为所有流量的入口,性能、稳定性是非常重要的一环,另外由于网关接入了内部所有的API,因此在大促时需要进行比较完善的压测,评估网关的容量,并进行扩容,但如果内部的业务比较复杂,网关接入了非常多的API,这种中心化的方案就会导致很难对网关进行比较准确的容量评估,后面可以考虑基于Service Mesh的思想,对网关进行去中心化改造,将网关的核心逻辑,比如鉴权、限流、协议转换、计费、监控、告警等都抽到sidecar中。
参考链接