网站的权重,请人做网站安全,公司网站运营维护单位,网页设计html代码大全继承关系介绍
在今年5月中#xff0c;Netflix终于开源了它的支持异步调用模式的Zuul网关2.0版本#xff0c;真可谓千呼万唤始出来。从Netflix的官方博文[附录1]中#xff0c;我们获得的信息也比较令人振奋#xff1a; The Cloud Gateway team at Netflix runs and operates more t…介绍
在今年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线程在处理的时候前台容器线程仍然是阻塞的。
同步阻塞模式有利有弊分析如下图 优势
同步阻塞模式的编程模型比较简单整个请求-处理-响应的流程(call flow)都是在一个线程中处理的这样开发调试比较方便易于理解比如出了问题跟踪调试比较方便。另外线程局部变量(ThreadLocal)机制在同步多线程模式下可以工作有些监控产品例如CAT调用链依赖于ThreadLocal在同步多线程模式下CAT埋点比较方便调用链关系的展示也比较直观。
不足
我们知道线程本身需要消耗CPU和内存资源且多线程之间切换是有开销的(所谓的上下文切换Context Switch开销)线程越多这种上下文切换的开销就越大同步阻塞模式一般会启动很多的线程必然引入线程切换开销。另外同步阻塞模式下容器线程池的数量一般是固定的造成对连接数有一定限制当后台服务慢容器线程池易被耗尽一旦耗尽容器会拒绝新的请求这个时候容器线程其实并不忙只是被后台服务调用IO阻塞但是干不了其它事情。
总体上同步阻塞模式比较适用于计算密集型(CPU bound)应用场景。对于IO密集型场景(IO bound)同步阻塞模式会白白消耗很多线程资源它们都在等待IO的阻塞状态没有做实质性工作。
Zuul 2.0编程模型和优劣 Zuul2的设计相对比较复杂代码也不太容易读懂它采用了Netty实现异步非阻塞编程模型如上图所示[图片来自附录4]。
一般异步模式的本质都是使用队列Queue(或称总线Bus)在上图中你可以简单理解为前端有一个队列专门负责处理用户请求后端有个队列专门负责处理后台服务调用中间有个事件环线程(Event Loop Thread)它同时监听前后两个队列上的事件有事件就触发回调函数处理事件。这种模式下需要的线程比较少基本上每个CPU核上只需要一个事件环处理线程前端的连接数可以很多连接来了只需要进队列不需要启动线程事件环线程由事件触发没有多线程阻塞问题。
异步非阻塞模式也是有利有弊分析如下图 优势
异步非阻塞模式启动的线程很少基本上一个CPU core上只需启一个事件环处理线程它使用的线程资源就很少上下文切换(Context Switch)开销也少。非阻塞模式可以接受的连接数大大增加可以简单理解为请求来了只需要进队列这个队列的容量可以设得很大只要不超时队列中的请求都会被依次处理。
不足
异步模式让编程模型变得复杂。一方面Zuul2本身的代码要比Zuul1复杂很多Zuul1的代码比较容易看懂Zuul2的代码看起来就比较费劲。另一方面异步模型没有一个明确清晰的请求-处理-响应执行流程(call flow)它的流程是通过事件触发的请求处理的流程随时可能被切换断开内部实现要通过一些关联id机制才能把整个执行流再串联起来这就给开发调试运维引入了很多复杂性比如你在IDE里头调试异步请求流就非常困难。另外ThreadLocal机制在这种异步模式下就不能简单工作因为只有一个事件环线程不是每个请求一个线程也就没有线程局部的概念所以对于CAT这种依赖于ThreadLocal才能工作的监控工具调用链埋点就不好搞(实际可以工作但需要进行特殊处理)。
总体上异步非阻塞模式比较适用于IO密集型(IO bound)场景这种场景下系统大部分时间在处理IOCPU计算比较轻少量事件环线程就能处理。
Zuul 1和Zuul 2的性能比对
Netflix本身对网关使用异步非阻塞模式这件事情是非常谨慎的它们进行了严格的性能测试下面是Netflix给出的一些性能数据来自Zuul2网关核心研发成员Arthur Gonigberg的ppt(Zuul’s Journey to Non-Blocking)[附录3] Netflix给出了一个比较模糊的数据大致Zuul2的性能比Zuul1好20%左右这里的性能主要指每节点每秒处理的请求数。为什么说模糊呢因为这个数据受实际测试环境流量场景模式等众多因素影响你很难复现这个测试数据。即便这个20%的性能提升是确实的其实这个性能提升也并不大和异步引入的复杂性相比这20%的提升是否值得是个问题。Netflix本身在其博文[附录4]和ppt[附录3]中也是有点含糊其词甚至自身都有一些疑问的。 While we did not see a significant efficiency benefit in migrating to async and non-blocking, we did achieve the goals of connection scaling. 比较明确的是Zuul2在连接数方面表现要好于Zuul1也就是说Zuul2能接受更多的连接数。
Zuul 2.0架构和额外特性 上图是Zuul2的架构和Zuul1没有本质区别两点变化
前端用Netty Server代替Servlet目的是支持前端异步。后端用Netty Client代替Http Client目的是支持后端异步。过滤器换了一下名字用Inbound Filters代替Pre-routing Filters用Endpoint Filter代替Routing Filter用Outbound Filters代替Post-routing Filters。上图是Zuul2的一些功能亮点我个人认为除了对HTTP/2的支持算是一个亮点其它都是在安全、弹性和运维层面的一些优化不能算新功能。其中像Request PassportStatus CategoriesRequest Attempts这些所谓的新功能其实是为了减轻异步带来的复杂性方便开发人员调试异步请求而专门开发的。
建议
基于上述分析我对大家的建议是在生产环境中继续使用Zuul1原因如下
Zuul1同步编程模型简单门槛低开发运维方便容易调试定位问题。Zuul2门槛高调试不方便。Zuul1监控埋点容易比如和调用链监控工具CAT集成如果你用Zuul2的话CAT不好埋点是个问题。Zuul1已经开源超过6年稳定成熟坑已经被踩平。Zuul2刚开源很新实际落地案例不多难说有bug需要踩坑。大部分公司达不到Netflix那个量级Netflix是要应对每日千亿级流量它们才挖空心思搞异步一般公司亿级可能都不到Zuul1绰绰有余。Zuul1可以集成Hystrix熔断组件可以部分解决后台服务慢阻塞网关线程的问题。Zuul1可以使用Servlet 3.0规范支持的AsyncServlet进行优化可以实现前端异步支持更多的连接数达到和Zuul2一样的效果但是不用引入太多异步复杂性。波波和极客时间合作的课程《微服务架构和实践160讲》7月份马上上线第三模块《微服务网关Zuul架构和实践》其中会讲解Zuul1如何使用AsyncServlet优化连接数欢迎大家关注。
对于Zuul2我的建议是持谨慎观望的态度可以在测试环境小规模实验验证但是暂不上到生产环境。
结论
同步异步各有利弊同步多线程编程模型简单但会有线程开销和阻塞问题异步非阻塞模式线程少并发高但是编程模型变得复杂。架构师做技术选型需要严谨务实具备批判性思维(Critical Thinking)即使是对于一线大公司推出的开源产品也要批判性看待不可盲目追新。个人建议生产环境继续使用Zuul1同步阻塞模式的一些不足可以使用熔断组件Hystrix和AsyncServlet等技术进行优化。波波和极客时间合作的课程《微服务架构和实践160讲》7月份马上上线第三模块《微服务网关Zuul架构和实践》其中会讲解对Zuul1的这些优化技术欢迎大家关注。
附录
Open Sourcing Zuul 2 Hystrix Zuul’s Journey to Non-Blocking Zuul2Netflix’s Journey to AsynchronousNon-blocking Systems