SpringCloud Gateway 和架构

Spring在 2017 年下半年迎来了WebfluxWebflux的出现填补了Spring在响应式编程上的空白,Webflux的响应式编程不仅仅是编程风格的改变,而且对于一系列的著名框架,都提供了响应式访问的开发包,比如Netty、Redis等等。 SpringCloud Gateway 使用的Webflux中的reactor-netty响应式编程组件,底层使用了Netty通讯框架。

SpringCloud Zuul 的 IO 模型

SpringCloud中所集成的Zuul版本,采用的是Tomcat容器,使用的是传统的Servlet IO处理模型。 大家知道,ServletServlet Container进行生命周期管理。 Container启动时构造Servlet对象并调用Servlet init()进行初始化; Container关闭时调用Servlet Destory()销毁ServletContainer运行时接受请求,并为每个请求分配一个线程(一般从线程池中获取空闲线程)然后调用service()。 弊端: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线程模型。用少量的线程处理requestresponse io操作,这些线程称为Loop线程,而业务交给响应式编程框架处理,响应式编程是非常灵活的,用户可以将业务中阻塞的操作提交到响应式框架的work线程中执行,而不阻塞的操作依然可以在Loop线程中进行处理,大大提高了Loop线程的利用率。官方结构图: Webflux虽然可以兼容多个底层的通信框架,但是一般情况下,底层使用的还是Netty,毕竟Netty是目前业界认可的最高性能的通信框架。而WebfluxLoop线程,正好就是著名的Reactor模式IO处理模型的Reactor线程,如果使用的是高性能的通信框架Netty,这就是NettyEventLoop线程。

Spring Cloud Gateway 的处理流程

客户端向 Spring Cloud Gateway 发出请求。然后在 Gateway Handler Mapping 中找到与请求相匹配的路由,将其发送到 Gateway Web HandlerHandler 再通过指定的过滤器链来将请求发送到我们实际的服务执行业务逻辑,然后返回。过滤器之间用虚线分开是因为过滤器可能会在发送代理请求之前(pre)或之后post执行业务逻辑。