Netflix Zuul与Nginx的性能对比

开发 开发工具
Spring Boot是一个用来构建单个微服务应用的理想选择,但是你还需要以某种方式将它们互相联系起来。这就是Spring Cloud试图解决的问题,尤其是Spring Cloud Netflix。

[[188450]]

如今你可以听到很多关于“微服务”的信息。Spring Boot是一个用来构建单个微服务应用的理想选择,但是你还需要以某种方式将它们互相联系起来。这就是Spring Cloud试图解决的问题,尤其是Spring Cloud Netflix。它提供了各种组件,比如:Eureka服务发现与Ribbon客户端负载均衡的结合,为内部“微服务”提供通信支持。但是,如果你想要与外界通信时(你提供外部API,或只是从你的页面使用AJAX),将各种服务隐藏在一个代理之后是一个明智的选择。

常规的选择我们会使用Nginx作为代理。但是Netflix带来了它自己的解决方案——智能路由Zuul。它带有许多有趣的功能,它可以用于身份验证、服务迁移、分级卸载以及各种动态路由选项。同时,它是使用Java编写的。如果Netflix使用它,那么它与本地反向代理相比是否足够快呢?或者当我们对灵活性(或其他功能)要求更高时,它是否适合与Nginx联合使用。

免责声明:不要认为这是一个严肃的基准。我只是想感受Nginx和Zuul的差异,因为我在互联网上并没有找到任何基准(也可能是我没有搜索足够长的时间)。它不遵循任何推荐的基准测试方法(预热时间、测试次数……),我只是使用3个在不同可用区域的EC2实例(这不是***的)。

测试

那我做了什么呢?测试是比较两种解决方案的原始性能,没有任何其他特殊的功能。我只是同时发起单个HTTP请求来获取一个HTML页面(大小约为26KB)。我使用ApacheBench来发起200个并发线程的测试(我也尝试了httpperf,但是它需要更高的CPU要求,所以还是选择了要求更低的ab)。

直接连接

首先,我感兴趣的是不通过任何反向代理直接访问HTTP服务器的性能。Ab在一台机器上运行,直接访问目标服务器。

  1. $ ab -n 10000 -c 200 http://target/sample.html 
  2. .... 
  3. Document Path: /sample.html 
  4. Document Length: 26650 bytes 
  5. Total transferred: 268940000 bytes 
  6. HTML transferred: 266500000 bytes 
  7. Requests per second: 2928.45 [#/sec] (mean) 
  8. Time per request: 68.295 [ms] (mean) 
  9. Time per request: 0.341 [ms] (mean, across all concurrent requests) 
  10. Transfer rate: 76911.96 [Kbytes/sec] received 
  11. Connection Times (ms) 
  12.  min mean[+/-sd] median max 
  13. Connect: 4 33 6.0 32 66 
  14. Processing: 20 35 7.5 35 392 
  15. Waiting: 20 35 6.4 34 266 
  16. Total: 24 68 7.8 66 423 
  17. Percentage of the requests served within a certain time (ms) 
  18.  50% 66 
  19.  66% 67 
  20.  75% 69 
  21.  80% 70 
  22.  90% 74 
  23.  95% 81 
  24.  98% 91 
  25.  99% 92 
  26.  100% 423 (longest request) 

很好,几次测试都显示了类似的值:2928、2725、2834、2648 req/s。有一些偏差,但这些数字现在还不重要。

通过Nginx

现在我可以使用Nginx的代理服务。只需要将Nginx配置更新为代理到目标服务器,比如:

  1. server { 
  2.    listen 80 default_server; 
  3.    listen [::]:80 default_server ipv6only=on
  4.    # Make site accessible from http://localhost/ 
  5.    server_name localhost; 
  6.    # allow file upload 
  7.    client_max_body_size 10M; 
  8.    location / { 
  9.       proxy_set_header X-Real-IP $remote_addr; 
  10.       proxy_set_header X-Forwarded-For $remote_addr; 
  11.       proxy_set_header Host $host; 
  12.       proxy_pass http://target:80; 
  13.    } 

像之前一样运行类型的测试:

  1. $ ab -n 50000 -c 200 http://proxy/sample.html 
  2. ... 
  3. Server Software: nginx/1.4.6 
  4. Server Hostname: proxy 
  5. Server Port: 80 
  6. Document Path: /sample.html 
  7. Document Length: 26650 bytes 
  8. Concurrency Level: 200 
  9. Time taken for tests: 52.366 seconds 
  10. Complete requests: 50000 
  11. Failed requests: 0 
  12. Total transferred: 1344700000 bytes 
  13. HTML transferred: 1332500000 bytes 
  14. Requests per second: 954.81 [#/sec] (mean) 
  15. Time per request: 209.465 [ms] (mean) 
  16. Time per request: 1.047 [ms] (mean, across all concurrent requests) 
  17. Transfer rate: 25076.93 [Kbytes/sec] received 
  18. Connection Times (ms) 
  19.  min mean[+/-sd] median max 
  20. Connect: 3 50 11.7 48 114 
  21. Processing: 37 159 11.9 160 208 
  22. Waiting: 36 159 11.9 160 207 
  23. Total: 40 209 10.4 209 256 
  24. Percentage of the requests served within a certain time (ms) 
  25.  50% 209 
  26.  66% 212 
  27.  75% 214 
  28.  80% 216 
  29.  90% 220 
  30.  95% 224 
  31.  98% 232 
  32.  99% 238 
  33.  100% 256 (longest request) 

测试结果为954、954、941 req/s。性能与延迟(如预期)变差了。

通过Zuul

现在我们在同一台机器上安装Zuul。它的应用本身很简单:

  1. @SpringBootApplication 
  2. @Controller 
  3. @EnableZuulProxy 
  4. public class DemoApplication { 
  5.     public static void main(String[] args) { 
  6.         new SpringApplicationBuilder(DemoApplication.class) 
  7.             .web(true).run(args); 
  8.     } 

我们还需要在 application.yml中定义固定的路由规则:

  1. zuul: 
  2.   routes: 
  3.     sodik: 
  4.       path: /sodik/** 
  5.       url: http://target 

现在我们试试运行测试:

  1. $ ab -n 50000 -c 200 http://proxy:8080/sodik/sample.html 
  2. Server Software: Apache-Coyote/1.1 
  3. Server Hostname: proxy 
  4. Server Port: 8080 
  5. Document Path: /sodik/sample.html 
  6. Document Length: 26650 bytes 
  7. Concurrency Level: 200 
  8. Time taken for tests: 136.164 seconds 
  9. Complete requests: 50000 
  10. Failed requests: 2 
  11. (Connect: 0, Receive: 0, Length: 2, Exceptions: 0) 
  12. Non-2xx responses: 2 
  13. Total transferred: 1343497042 bytes 
  14. HTML transferred: 1332447082 bytes 
  15. Requests per second: 367.20 [#/sec] (mean) 
  16. Time per request: 544.657 [ms] (mean) 
  17. Time per request: 2.723 [ms] (mean, across all concurrent requests) 
  18. Transfer rate: 9635.48 [Kbytes/sec] received 
  19. Connection Times (ms) 
  20. min mean[+/-sd] median max 
  21. Connect: 2 12 92.3 2 1010 
  22. Processing: 15 532 321.6 461 10250 
  23. Waiting: 10 505 297.2 441 9851 
  24. Total: 17 544 333.1 467 10270 
  25. Percentage of the requests served within a certain time (ms) 
  26. 50% 467 
  27. 66% 553 
  28. 75% 626 
  29. 80% 684 
  30. 90% 896 
  31. 95% 1163 
  32. 98% 1531 
  33. 99% 1864 
  34. 100% 10270 (longest request) 

结果比我(乐观的)猜测更差。此外,我们还能看到两次请求失败(我们可以在Zuul的日志中看到有两个相应的异常,这些异常引发了HTTP连接池超时)。显然默认情况下超时时间为10秒。

我们再进一步测试,得到了更多的结果:

  1. Document Path: /sodik/sample.html 
  2. Document Length: 26650 bytes 
  3. Concurrency Level: 200 
  4. Time taken for tests: 50.080 seconds 
  5. Complete requests: 50000 
  6. Failed requests: 0 
  7. Total transferred: 1343550000 bytes 
  8. HTML transferred: 1332500000 bytes 
  9. Requests per second: 998.39 [#/sec] (mean) 
  10. Time per request: 200.322 [ms] (mean) 
  11. Time per request: 1.002 [ms] (mean, across all concurrent requests) 
  12. Transfer rate: 26199.09 [Kbytes/sec] received 
  13. Connection Times (ms) 
  14. min mean[+/-sd] median max 
  15. Connect: 2 16 7.9 16 126 
  16. Processing: 15 184 108.1 203 1943 
  17. Waiting: 13 183 105.9 202 1934 
  18. Total: 18 200 107.8 218 1983 
  19. Percentage of the requests served within a certain time (ms) 
  20. 50% 218 
  21. 66% 228 
  22. 75% 235 
  23. 80% 239 
  24. 90% 254 
  25. 95% 287 
  26. 98% 405 
  27. 99% 450 
  28. 100% 1983 (longest request) 

哇,不错的改善。我认为Java JIT编译对于性能有一定的帮助,但是要验证这是否只是一个巧合,再尝试一次:1010 req / sec。最终结果对我来说是一个惊喜。

结论

Zuul的原始性能非常接近于Nginx。事实上,在启动预热之后,我的测试结果甚至略好一些(重申免责声明-这并非一个严肃的基准性能测试)。Nginx显示出更多的可预测性能(变化较小),可悲的是在Zuul预热期间,我们经历了一些小故障(150000个请求中的2个,但是您的微服务应该是容错机制的,对吧?)。

所以,如果您考虑使用一些Zuul的额外功能,或者希望通过它与其他Netflix服务集成(比如Eureka)获得更多的服务能力,Zuul看起来非常有希望作为简单反向代理的替代产品。也许这也是Netflix使用的原因,所以您也可以尝试一下。

【本文为51CTO专栏作者“翟永超”的原创稿件,转载请通过51CTO联系作者获取授权】

戳这里,看该作者更多好文

责任编辑:武晓燕 来源: 51CTO专栏
相关推荐

2017-11-20 13:54:55

FlinkStorm框架

2017-11-21 15:50:09

FlinkStorm性能

2009-11-20 09:01:13

Ubuntu性能对比

2024-01-05 08:46:50

ReactVue

2011-08-25 17:29:40

LUAPHPWEB

2011-12-14 11:38:42

PhoneGapJavaAndroid

2022-12-05 17:01:20

MySQL数据库Oracle

2024-10-09 11:31:51

2019-12-25 09:53:01

虚拟机技术固态硬盘

2013-07-17 17:03:23

Ngx_luaNginx

2019-09-24 13:53:19

MySQLMySQL 8.0数据库

2009-07-24 13:17:43

世纪互联至强CloudEx

2011-08-05 10:01:47

MySQL库Pdo-MysqlMysqli

2012-07-13 10:57:46

Nginxlua

2010-01-22 11:06:03

GNUkFreeBSDLinux

2010-06-28 13:11:05

2010-01-16 11:02:12

Ubuntu性能测试

2012-08-16 13:24:58

Windows 8Windows 7对比

2013-12-23 09:37:16

Fedora开源Fedora 19

2021-07-26 09:45:24

Windows 11WSL2Linux
点赞
收藏

51CTO技术栈公众号