API网关 Zuul1.0 和 2.0 我们该如何选择?

介绍

在今年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)场景,这种场景下系统大部分时间在处理IO,CPU计算比较轻,少量事件环线程就能处理。

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没有本质区别,两点变化:

  1. 前端用Netty Server代替Servlet,目的是支持前端异步。后端用Netty Client代替Http Client,目的是支持后端异步。
  2. 过滤器换了一下名字,用Inbound Filters代替Pre-routing Filters,用Endpoint Filter代替Routing Filter,用Outbound Filters代替Post-routing Filters。

上图是Zuul2的一些功能亮点,我个人认为除了对HTTP/2的支持算是一个亮点,其它都是在安全、弹性和运维层面的一些优化,不能算新功能。其中像Request Passport,Status Categories,Request Attempts这些所谓的新功能,其实是为了减轻异步带来的复杂性,方便开发人员调试异步请求而专门开发的。

建议

基于上述分析,我对大家的建议是在生产环境中继续使用Zuul1,原因如下:

  1. Zuul1同步编程模型简单,门槛低,开发运维方便,容易调试定位问题。Zuul2门槛高,调试不方便。
  2. Zuul1监控埋点容易,比如和调用链监控工具CAT集成,如果你用Zuul2的话,CAT不好埋点是个问题。
  3. Zuul1已经开源超过6年,稳定成熟,坑已经被踩平。Zuul2刚开源很新,实际落地案例不多,难说有bug需要踩坑。
  4. 大部分公司达不到Netflix那个量级,Netflix是要应对每日千亿级流量,它们才挖空心思搞异步,一般公司亿级可能都不到,Zuul1绰绰有余。
  5. Zuul1可以集成Hystrix熔断组件,可以部分解决后台服务慢阻塞网关线程的问题。
  6. Zuul1可以使用Servlet 3.0规范支持的AsyncServlet进行优化,可以实现前端异步,支持更多的连接数,达到和Zuul2一样的效果,但是不用引入太多异步复杂性。波波和极客时间合作的课程《微服务架构和实践160讲》,7月份马上上线第三模块《微服务网关Zuul架构和实践》,其中会讲解Zuul1如何使用AsyncServlet优化连接数,欢迎大家关注。

对于Zuul2,我的建议是持谨慎观望的态度,可以在测试环境小规模实验验证,但是暂不上到生产环境。

结论

  1. 同步异步各有利弊,同步多线程编程模型简单,但会有线程开销和阻塞问题,异步非阻塞模式线程少并发高,但是编程模型变得复杂。
  2. 架构师做技术选型需要严谨务实,具备批判性思维(Critical Thinking),即使是对于一线大公司推出的开源产品,也要批判性看待,不可盲目追新。
  3. 个人建议生产环境继续使用Zuul1,同步阻塞模式的一些不足,可以使用熔断组件Hystrix和AsyncServlet等技术进行优化。波波和极客时间合作的课程《微服务架构和实践160讲》,7月份马上上线第三模块《微服务网关Zuul架构和实践》,其中会讲解对Zuul1的这些优化技术,欢迎大家关注。

附录

  1. Open Sourcing Zuul 2

  2. Hystrix

  3. Zuul’s Journey to Non-Blocking

  4. Zuul2:Netflix’s Journey to Asynchronous,Non-blocking Systems


money.jpg

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/477656.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode 623. 在二叉树中增加一行(BFS/DFS)

文章目录1. 题目2. 解题2.1 BFS2.2 DFS1. 题目 给定一个二叉树,根节点为第1层,深度为 1。在其第 d 层追加一行值为 v 的节点。 添加规则:给定一个深度值 d (正整数),针对深度为 d-1 层的每一非空节点 N&a…

论文浅尝 | KR-GCN: 知识感知推理的可解释推荐系统

论文作者:马婷,中国科学院信息工程研究所直博生动机抽取并利用知识图谱(KG)中的多跳关系路径可以提高推荐系统的性能,并提供可解释性。然而,现有的工作仍面临着两个主要的挑战:用户偏好的错误传播和模型的弱解释性。提…

吴恩达,确诊新冠阳性!

编 | 好困 袁榭源 | 新智元【导读】当代人工智能领域最权威的学者之一吴恩达,于2022年2月8日晨在自己推特上宣布新冠检测结果阳性,不过症状轻微。北京时间,2022年2月8日早上6点,吴恩达新冠病毒检测呈阳性。吴恩达表示,…

Spring Cloud Config采用Git存储时两种常用的配置策略

由于Spring Cloud Config默认采用了Git存储,相信很多团队在使用Spring Cloud的配置中心时也会采用这样的策略。即便大家都使用了Git存储,可能还有各种不同的配置方式,本文就来介绍一下两种常用的配置策略。 第一种:多个项目公用一…

图谱实战 | 城市大脑知识图谱构建及应用研究

转载公众号 | 专知随着城市大脑建设进程的推进,城市中积累了大量的物联网(IoT)设备和数据,利用海量设备数据对问题 进行分析和溯源,对于城市大脑建设具有重要意义。该文基于资源描述框架和智能物联网协议概念,提出一种以城市物联网本体为基础的城市大脑知识图谱建设方法,城市大…

震惊!三个万引大佬嘴仗,原来是为了他……?

文|白鹡鸰想把小轶挂到三作编|小轶已把白鹡鸰挂到三作这本应是白鹡鸰在小轶追杀下游刃有余拖稿的一天,结果小轶再次把一篇新论文喂到了我的嘴边。象征性地打开论文,草草扫过去,嗯,迁移学习,嗯&a…

LeetCode 611. 有效三角形的个数(双指针)

1. 题目 给定一个包含非负整数的数组,你的任务是统计其中可以组成三角形三条边的三元组个数。 示例 1: 输入: [2,2,3,4] 输出: 3 解释: 有效的组合是: 2,3,4 (使用第一个 2) 2,3,4 (使用第二个 2) 2,2,3注意: 数组长度不超过1000。 数组里整数的范围为 [0, 1000]…

Eureka 2.0 开源流产,真的对你影响很大吗?

最近连续发烧四天,偶尔刷两下朋友圈都能看到好几条来自不同号的关于《Eureka 2.0开源工作宣告停止,继续使用风险自负》的推文。主要内容如下: 近日,知名服务注册与服务发现工具 Eureka 的 GitHub Wiki 上显示其 2.0 版本的开源工作…

会议交流 | 知识图谱开源开放及生态——7月12日TF65

转载公众号 | 中国计算机学会本期会议邀请到来自阿里巴巴等头部企业的代表,以及来自北京大学、南京大学和浙江大学的研究人员,一起深入探讨开放知识图谱、知识图谱开源工具等所面临的机遇和挑战,并进一步了解知识图谱开放和开源工具构建的应用…

LeetCode 650. 只有两个键的键盘(DP)

1. 题目 最初在一个记事本上只有一个字符 ‘A’。你每次可以对这个记事本进行两种操作: Copy All (复制全部) : 你可以复制这个记事本中的所有字符(部分的复制是不允许的)。Paste (粘贴) : 你可以粘贴你上一次复制的字符。 给定一个数字 n 。你需要使用最少的操作…

10个开源工业检测数据集汇总

本文转载自公众号“夕小瑶的卖萌屋”,专业带逛互联网算法圈的神操作 -----》我是传送门 关注后,回复以下口令: 回复【789】 :领取深度学习全栈手册(含NLP、CV海量综述、必刷论文解读) 回复【入群】&#xf…

Hystrix降级逻辑中如何获取触发的异常

通过之前Spring Cloud系列教程中的《Spring Cloud构建微服务架构:服务容错保护(Hystrix服务降级)》一文,我们已经知道如何通过Hystrix来保护自己的服务不被外部依赖方拖垮的情况。但是实际使用过程中经常碰到开发反应“莫名”触发…

大厂生存36计

本文授权转载自公众号“算法圈的小破事”,点击以上卡片进行关注大家好,我是在互联网危险边缘疯狂试探的皮皮虾。互联网大厂就像一座围城,外面人想进去,里面的人想出去。里面的人说又累又不好混,外面的人觉得里面的人舒…

开源开放 | 多模态地球科学知识图谱GAKG

OpenKG地址:http://openkg.cn/dataset/gakg网站地址:https://gakg.acemap.info/论文地址:https://dl.acm.org/doi/10.1145/3459637.3482003开放许可协议:CC BY-SA 4.0 (署名相似共享)贡献者:王新…

LeetCode 468. 验证IP地址

1. 题目 编写一个函数来验证输入的字符串是否是有效的 IPv4 或 IPv6 地址。 IPv4 地址由十进制数和点来表示,每个地址包含4个十进制数,其范围为 0 - 255, 用(".")分割。比如,172.16.254.1; 同时&#xff…

Spring Cloud Config采用数据库存储配置内容【Edgware+】

在之前的《Spring Cloud构建微服务架构:分布式配置中心》一文中,我们介绍的Spring Cloud Server配置中心采用了Git的方式进行配置信息存储。这一设计巧妙的利用Git自身机制以及其他具有丰富功能的Git服务端产品,让Spring Cloud Server在配置存…

颤抖吧,打工人!深信服推出员工离职倾向、工作摸鱼监测系统!

文 | 金磊 杨净(发自凹非寺)源 | 量子位前脚投简历,后脚就被精准裁员。一位网友最近就爆出了这样一段真实经历,而且还称被领导教育了一通:别以为你上班干啥我都不知道,你啥时候想走我都一清二楚&#xff01…

征稿 | “知识图谱赋能的知识工程:理论、技术与系统”专题投稿截止时间延长至2022年7月25日...

转载公众号 | 计算机科学编辑部征稿“知识图谱赋能的知识工程:理论、技术与系统”专题知识图谱(Knowledge Graph)方法与技术是人工智能在知识工程领域发展的最新前沿。知识图谱正在“感知智能”迈向“认知智能”的过程中扮演着重要角色。近年…

LeetCode 93. 复原IP地址(回溯)

1. 题目 给定一个只包含数字的字符串,复原它并返回所有可能的 IP 地址格式。 示例: 输入: "25525511135" 输出: ["255.255.11.135", "255.255.111.35"]来源:力扣(LeetCode) 链接:http…

为什么回归问题用MSE?

文 | Matrix.小泽直树最近在看李沐的实用机器学习课程,讲到regression问题的loss的时候有弹幕问:“为什么要平方?”如果是几年前学生问我这个问题,我会回答:“因为做回归的时候的我们的残差有正有负,取个平…