介绍
在今年5月中,Netflix终于开源了它的支持异步调用模式的Zuul网关2.0版本,真可谓千呼万唤始出来。从Netflix的官方博文[附录1]中,我们获得的信息也比较令人振奋:
The Cloud Gateway team at Netflix runs and operates more than 80 clusters of Zuul 2, sending traffic to about 100 (and growing) backend service clusters which amounts to more than 1 million requests per second.
Netflix部署了超过80+的Zuul2云网关集群,流量经过Zuul2集群被路由到后端超过100+的微服务,且每秒钟经过Zuul2集群的请求超过100万。
Zuul2看起来很强大,支持异步高并发(Zuul1仅支持同步)特性看起来很亮眼,那么我们是否就应该抛弃Zuul1,开始拥抱Zuul2呢?作为架构师,我们不能盲目追时髦,技术的选择必须基于实践和理性的分析,基于我之前对Zuul1的一线落地实战经验,也基于我近期对Zuul2的一些调研,我会在本文中对Zuul1和Zuul2做一个比较客观的编程模型和优劣分析,同时给出我的个人建议。
Zuul 1.0编程模型和优劣
Zuul1设计比较简单,代码不多也比较容易读懂,它本质上就是一个同步Servlet,采用多线程阻塞模型,如上图所示[图片来自附录4]。
同步Servlet使用thread per connection方式处理请求。简单讲,每来一个请求,Servlet容器要为该请求分配一个线程专门负责处理这个请求,直到响应返回客户端这个线程才会被释放返回容器线程池。如果后台服务调用比较耗时,那么这个线程就会被阻塞,阻塞期间线程资源被占用,不能干其它事情。我们知道Servlet容器线程池的大小是有限制的,当前端请求量大,而后台慢服务比较多时,很容易耗尽容器线程池内的线程,造成容器无法接受新的请求,Netflix为此还专门研发了Hystrix[附录2]熔断组件来解决慢服务耗尽资源问题。
注意在上图Netflix给出的场景中,它的后台服务调用也是启动另外一个IO线程来处理的,但是本质上还是阻塞模式,后台IO线程在处理的时候,前台容器线程仍然是阻塞的。
同步阻塞模式有利有弊,分析如下图: