转自:http://www.servicemesh.cn/?/article/45

作者:Turgay Çelik

翻译:钟毅(Drew Zhong)

原文:Comparing API Gateway Performances: NGINX vs. ZUUL vs. Spring Cloud Gateway vs. Linkerd

不管是从团队人数,还是从公司产品的特性的角度来看,我们 OpsGenie 都处于快速成长的过程中。举例来说,仅就去年一年,我们的工程师团队人数由15人增长到50人。同时我们遵从了 Two Pizza team rule ,将工程师团队每8人分成一组,以更好地适应团队总人数的迅速增长。

你可能也猜到,目前 OpsGenie 的产品已经有点类似巨石应用了。由于多个团队共同开发维护同一个产品 以及 CI/CD ( Continuous Integration/Continuous Delivery ) 流程等原因,产品的开发和维护已经变得极具挑战。因此,我们不得不紧随当下的趋势,将巨石应用向分布式架构转变。读者可以从 Martin Fowler 的文章中,了解更多关于微服务架构和它的优点。

在对微服务概念的实践中,有一些值得推荐的架构模式。而 API 网关就是这些模式中的一个。简单来说,API 网关就是所有客户端的统一入口。它通过两种方式来处理客户端请求:一是作为代理,将请求路由给某一个特定的服务;二是将请求分散给多个服务。 API 网关是微服务框架的一个很好的开端,因为一个巨石应用微服务化后能够得到多个不同的服务,而API 网关能将特定的请求路由给特定的服务。

实际上,API 网关对我们来说并不是一个新的概念。我们用 Nginx 来作为我们巨石应用的 API 网关已经很长一段时间了,但是既然我们已经打算向微服务转型,那我们就不得不重新评估 Nginx 是不是一个好的选择。性能、可扩展性以及像限流等其它特性,都是我们需要考虑的。当然网关的性能,尤其是在高并发场景下能否满足我们的需求,才是我们最在意的。

在本篇博文中,我们将阐述如何搭建我们的测试环境,并比较 Zuul 1、Nginx、Spring Cloud Gateway 和 Linkerd。事实上,我们还有像 Lyft 的 Envoy 和 UnderTow 等其它备用方案。我们会对这些工具进行同样的测试,然后在以后的博文中再分享结果。

Zuul 1 对我们团队而言是一个不错的选择。因为它是由 Java 开发的,而且也完美兼容 Spring 框架。目前,已经有一些博客是进行 Zuul 和 Nginx 的比较的。但我们同时也想要比较 Spring Cloud 网关和 Linkerd,另外,我们也希望进行更一步的压力测试。所以,我们决定搭建我们自己的环境来进行测试。

为了客观地评估各个 API 网关自身的性能,我们创建了一个独立于 OpsGenie 产品之外的 隔离的测试环境。我们使用 Apache Http Server Benchmarking tool — ab 来搭建我们的测试环境。

首先,我们根据 Nginx 的官方文档,在 AWS EC2 t2.micro 实例上部署 Nginx 。这是我们的初始测试环境。然后我们在这个环境之上,又部署了 Zuul 和 Spring Cloud Gateway。Nginx web 服务器中放置了一些静态资源,然后我们分别在 Nginx、Zuul 和 Spring Cloud Gateway 上定义一些指向 web 服务器的反向代理。然后我们将另一个 t2.micro EC2 作为客户端,来发起一些请求。

图中带箭头的虚线就是我们测试用的路径。主要有以下五种方式:

· 直连

· 通过 Nginx 反向代理请求

· 通过 Zuul 请求

· 通过 Spring Cloud Gateway 请求

· 通过 Linkerd 请求

鉴于读者往往更关心结果,所以接下来我们会先给出测试结果,然后再进行详细的解释。

Benchmark性能总数

测试策略
我们使用 Apache 的 HTTP 服务器 Benchmark 工具。每一轮,我们用200个线进行10000次请求。

ab -n 10000 -c 200 HTTP://<server-address>/<path to resource>

我们在三种不同配置的 AWS EC2 上进行测试。为了更好地说明真实的请求, 我们对每一轮测试都进行了细分:

· 为了了解代理本身所需要的开销,我们首先对直连方式进行了额外的单独测试。但介于直连并不是我们的待选方案,因此后面的几轮就不再对直连进行测试。

· 介于 Spring Cloud Gateway 至今还没有正式发版,因此我们只会在最后一轮对它进行测试。

· Zuul 在调用过一次之后的性能表现会更好。我们认为这是 JIT 优化 (Just In Time) 的效果。所以我们形象地将 Zuul 的第一次运行称作是“热身”。当然,下面各个表中的数值都是 Zuul“热身”之后的性能。

· 我们都知道,Linkerd 是一种很吃资源的代理方式,因此我们就只在最后一轮,即性能配置最佳的方案中才会进行对它的比较。

测试用配置
T2.Micro --单核、1g内存:我们在这个配置上进行直连、Nginx 反向代理和 Zuul (热身后)三种代理方式的测试 M4.Large --双核、8g内存:我们在这个配置上进行 Nginx 反向代理和 Zuul (热身后)两种代理方式的测试 M4.2xLarge --八核、32g内存:我们在这个配置上进行 Nginx 反向代理、Zuul(热身后)、Spring Cloud Gateway 和 Linkerd 四种代理方式的测试
测试结果

以下是性能测试结果的概要:

测试的细节
直连
首先,我们在不使用任何代理的情况下直接访问静态资源。结果如下图所示。每次请求所需要的响应时间是30ms。

通过 Nginx 反向代理连接

在第二次测试中,我们通过Nginx反向代理访问资源。每次请求的响应时间为40ms。我们发现,和上一部分不使用任何代理的直连方式相比,Nginx反向代理平均增加了33%的耗时。

通过 Zuul 反向代理的连接

首先,我们创建了一个如下 Spring Boot 应用程序:

以下是我们的 application.yml 配置文件

Zuul“热身”测试的结果如下:

直连和通过 Nginx 反向代理的方式分别耗时30ms和40ms。在 Zuul 的首轮测试中,每一次请求响应耗时为388ms。正如其它博客中提到的那样,JVM 热身会有所帮助。我们又重新对 Zuul 进行一轮测试,结果如下:

Zuul在“热身”之后的性能确实有所提高,每一次请求的响应时间下降到了200ms,但是和 Nginx 反向代理平均40ms的耗时相比,还是有比较大的差距的。
将服务器升级到m4.large

正如图一所示,t2.micro ec2 仅仅是单核 1G 内存。Nginx 是 c++ 程序而 Zuul 是 Java 语言实现的。众所周知,Java 应用程序对性能的要求会更高一些。因此我们使用 m4.large 服务器(双核,8G)来进行测试。 我们再一次对 Nginx 和 Zuul 两种反向代理方式分别进行测试,结果如下:

正如以上两幅图所示,Nginx 和 Zuul 的请求响应时间分别是32ms和95ms。结果要远好于在 t2.micro 服务器进行测试时的结果。 当然,以上测试还有一个明显值得争议的问题:我们是通过 Spring Boot 应用程序来使用 Zuu l的,这自然会带来额外的性能消耗。如果我们单独对 Zuul 来进行测试,那么测试的性能结果可能还会更好。
将服务器升级到m4.2xlarge?
我们也在 m4.2xlarge 的机器(8核,32G内存)上进行了测试,Nginx 和 Zuul 的结果分别如下:

在 m4.2xlarge 的机器上,Zuul 的性能要好于 Nginx。我们想要知道 Netflix 公司是使用的哪一种 EC2 来运行 Zuul 实例的,但是却找不到对应的答案。在其它的一些博文中会有人抱怨 Zuul 的性能,然后也在询问 Netflix 公司扩展它的方式,我们觉得这次的测试结果就是答案:Zuul 的性能受限于 CPU,所以必须加 CPU。

Linkerd的测试

Linkerd 是一个云原生计算基金会的项目。它是一个 Scala 语言实现的 Service Mesh / 服务网格 应用程序,提供如服务发现等能力,但它同时也提供了反向代理的能力。我们测试了 Linkerd 的性能,结果如下图所示。Linkerd 的性能非常接近 Zuul。

Spring Cloud Gateway的测试

Spring Cloud 社区也在开发一个网关组件。虽然官方还没有正式发布这款组件,但我们认为还是需要将它和其他的可选组件一同来进行比较。因此,我们根据我们的测试环境修改了 Spring Cloud Gateway 应用程序的范例。 我们对它进行了同样的性能测试,通过 Apache Http 服务器性能测试工具,用200个并发线程进行10000次请求。结果如下: 此处输入链接的描述 如图所示,Spring Cloud Gateway 每秒处理873个请求,每个请求的响应时间是229ms。从我们测试的结果看来,Spring Cloud Gateway 并达不到 Zuul、Linkerd 和 Nginx 的水平,至少从它们当前各自 Github 上的代码是可以得到这样子的结论的。

接下来的工作

在本篇博客中,我们用Apache Http服务器性能测试工具对Zuul、Nginx、Linkerd和Spring Cloud Gateway进行了测试。以下是我们接下来的一些计划:

我们准备对 Envoy 进行评估。实际上 Envoy 不仅仅是一个 API 网关,它同时也是 Service Mesh/服务网格应用。

Undertow 也提供了反向代理的能力,也是我们接下来需要评估的。

Netflix 重新设计了 Zuul,将它设计成基于 Netty 的非阻塞应用。这个新版本叫作 "Zuul 2".我们准备在其开源版本正式发布后对其进行性能测试,然后再分享这一新 Zuul 的测试结果。

Spring Cloud Gateway 尚未开发完成,它是一个 Java 语言的基于 Netty 的非阻塞网关,因此它对于我们来说也是一个不错的选择。我们同样会对其官网版本进行性能测试。

API 网关中,一些是阻塞的,比如 Nginx 和 Zuul 1,另外一些是非阻塞的,比如 Zuul 2、Linkerd、Envoy。阻塞架构的好处在于开发简单,易于请求的追踪,但同时也会导致扩展方面的问题。非阻塞架构在开发和追踪方面会复杂一些,但是它的扩展能力和弹性伸缩能力要更加出色。因此我们加下来也会对这两种架构方案做出选择我们也会对 Gatling 进行一些测试,并在下一篇博客中分享测试结果。

我们会在接下来的每一篇博文中都对我们所取得的进展和发现进行分享,敬请期待。

这压测结果有问题。spring cloud gateway使用ab压测数据是不准的。原因是reactor-netty使用ab压测有个问题。

详见:github.com/reactor/reactor-netty/issues/21
有人提出的疑问:github.com/spring-cloud/spring-cloud-gateway/issues/124
官方的压测:github.com/spencergibb/spring-cloud-gateway-bench

实测 | 转型微服务,这4大工具谁是API网关性能最优?的更多相关文章

  1. Spring Boot、微服务架构和大数据

    一文读懂 Spring Boot.微服务架构和大数据治理三者之间的故事 https://www.cnblogs.com/ityouknow/p/9034377.html 微服务架构 微服务的诞生并非偶 ...

  2. 庐山真面目之六微服务架构Consul集群、Ocelot网关集群和Nginx版本实现

    庐山真面目之六微服务架构Consul集群.Ocelot网关集群和Nginx版本实现 一.简介      在上一篇文章<庐山真面目之五微服务架构Consul集群.Ocelot网关和Nginx版本实 ...

  3. 庐山真面目之七微服务架构Consul集群、Ocelot网关集群和IdentityServer4版本实现

    庐山真面目之七微服务架构Consul集群.Ocelot网关集群和IdentityServer4版本实现 一.简介      在上一篇文章<庐山真面目之六微服务架构Consul集群.Ocelot网 ...

  4. 一文读懂 Spring Boot、微服务架构和大数据治理三者之间的故事

    微服务架构 微服务的诞生并非偶然,它是在互联网高速发展,技术日新月异的变化以及传统架构无法适应快速变化等多重因素的推动下诞生的产物.互联网时代的产品通常有两类特点:需求变化快和用户群体庞大,在这种情况 ...

  5. 构建微服务-使用OAuth 2.0保护API接口

    微服务操作模型 基于Spring Cloud和Netflix OSS 构建微服务-Part 1 基于Spring Cloud和Netflix OSS构建微服务,Part 2 在本文中,我们将使用OAu ...

  6. Spring Boot + Spring Cloud 构建微服务系统(七):API服务网关(Zuul)

    技术背景 前面我们通过Ribbon或Feign实现了微服务之间的调用和负载均衡,那我们的各种微服务又要如何提供给外部应用调用呢. 当然,因为是REST API接口,外部客户端直接调用各个微服务是没有问 ...

  7. 微服务之十四如何在 Ocelot 网关中配置多实例 Swagger 访问

    一.介绍 当我们开发基于微服务的应用程序的时候,有一个环节总是跳不过去的,那就是要创建 WebApi,然后,我们的应用程序基于 WebApi 接口去访问.在没有 Swagger 以前,我们开发好了 W ...

  8. 微服务测试打桩/mock工具mountebank

    1,安装 Linux安装包,不用安装Node.js https://s3.amazonaws.com/mountebank/v1.10/mountebank-v1.10.0-linux-x64.tar ...

  9. SpringBoot微服务电商项目开发实战 --- api接口安全算法、AOP切面及防SQL注入实现

    上一篇主要讲了整个项目的子模块及第三方依赖的版本号统一管理维护,数据库对接及缓存(Redis)接入,今天我来说说过滤器配置及拦截设置.接口安全处理.AOP切面实现等.作为电商项目,不仅要求考虑高并发带 ...

随机推荐

  1. Scala中=>的用法

    1. 表示函数的类型(Function Type) 例如: def double(x: Int): Int = x*2 函数double的类型就是 (x: Int) => Int 或者 Int ...

  2. elastic-job+zookeeper实现分布式定时任务调度的使用(springboot版本)

    总体思路,要确认一个定时任务需要一个cron表达式+jobDetail: 现在要让实现定时任务的协调,则就让zookeeper,简单说就是需要3要素,zk对象+cron+jobDetail: 总的项目 ...

  3. 【JUC源码解析】SynchronousQueue

    简介 SynchronousQueue是一种特殊的阻塞队列,该队列没有容量. [存数据线程]到达队列后,若发现没有[取数据线程]在此等待,则[存数据线程]便入队等待,直到有[取数据线程]来取数据,并释 ...

  4. 关于IntelliJ IDEA 创建Maven项目速度慢

    在maven的VM Options加上-DarchetypeCatalog=internal参数,如下:

  5. Struts 2 访问Servlet API的方式

    与Servlet API解耦的访问方式 与Servlet API耦合的访问方式 (tips:耦合既依赖) 1.    与Servlet API解耦的访问方式 2.     与Servlet API耦合 ...

  6. How to: Provide Credentials for the Dashboards Module when Using External Data Sources

    XAF中使用dashboard模块时,如果使用了sql数据源,可以使用此方法提供连接信息 https://www.devexpress.com/Support/Center/Question/Deta ...

  7. JUC——线程同步锁(ReentrantReadWriteLock读写锁)

    读写锁简介 所谓的读写锁值得是两把锁,在进行数据写入的时候有一个把“写锁”,而在进行数据读取的时候有一把“读锁”. 写锁会实现线程安全同步处理操作,而读锁可以被多个对象读取获取. 读写锁:ReadWr ...

  8. 《图解 HTTP 》阅读 —— 第一章

    第1章 了解web及网络基础 计算机与网络设备相互通信的规则称为协议,比如:如何探测到通信目标.由哪一边发起通信.使用那种语言进行通信.怎么结束通信等. TCP/IP 协议族按照层次分为以下四层:应用 ...

  9. 一个可以自由存取的onedriver

    https://cittedu-my.sharepoint.com/personal/jostin_5gd_me/Documents/jostin

  10. Django_rest_framework_Serializer

    序列化Serializer 序列化用于对用户请求数据进行验证和数据进行序列化(为了解决queryset序列化问题). 那什么是序列化呢?序列化就是把对象转换成字符串,反序列化就是把字符串转换成对象 m ...