Pipy 性能基准测试的思考与实践
这篇文章由一次线上活动的分享整理而成,活动中分享了我们在做 Pipy 的延迟基准过程的思考,以及实践的内容。
测试使用的自动化脚本以及实施说明都可以从 GitHub 仓库下载,欢迎有兴趣的同学下载测试。后续我们还有更多的测试,也会更新到这个仓库。
Pipy 是面向云、边缘和 IoT 的开源的可编程代理,可编程特性使其可以灵活多变地应对众多场景。至于为什么需要可编程代理可以参考这篇文章,这里不做展开。本文主要分享代理性能基准测试的实践。
背景
代理也称代理服务器,通常作为两个互相隔离的网络的沟通桥梁,允许一侧的终端可以访问另一侧的服务,实现网络的连通。
早在互联网的早期,很多系统直接对外提供服务,后来由于安全性等因素的考虑,引入了代理来承担了最为基础的网络连通的角色,在最小化暴露面的前提下实现服务的可访问。此时系统流量还比较小,并且业务也没那么复杂,基本单台的服务器足以消化了负载,但随着互联网尤其是移动互联网的发展,访问系统的终端越来越多,流量越来越大。单台服务器不论是连接容量还是处理能力都无法满足需要,何况业务也变得越来越复杂。
为了解决此类问题,实现系统的高性能和高可用,系统维护者引入了分布式的概念,通过部署多台服务器来增加服务的容量,多台服务器以集群的方式对外提供服务。同时通过比如会话保持或者无状态服务等手段,保证用户的请求可以被任意一台服务器正确处理。此时,代理又“负担”了更多的功能:
路由
负载均衡
故障转移
访问控制
身份识别
网络加速
指标采集
信息安全
代理的引入以及功能的膨胀,也增加了开销,对用户最大的影响是增加了延迟。
什么是延迟
延迟简单讲就是一次操作所需要的时间,对于一次网络请求来说从发出请求到接受响应的这段时间就是延迟,实际包含了发送请求的延迟和接受响应的延迟,通常情况下则是将二者合起来。
在引入了代理之后,相当于请求做了一次中转,并且由于代理众多的功能处理延迟也相应地增加了。因此对延迟的影响,成为衡量代理能力的一个指标。
延迟的测量
过往经常听到有人说我们的服务延迟不到 100ms,性能如何如何强,但是一到了真实环境中就拉胯。
下面是从网络找到的一幅图,展示的是系统在某个时间内,系统的延迟情况。
二者都是同样的表述,核心就是平均延迟。这就像某大厂公布财报,人均年薪 80+w。但是员工一听傻眼了,有的说哪有这么少,也有的说。。。
统计的方式并没有问题,这就是常说的平均值陷阱。当将数据展开用百分比分布的方式来看,就能发现问题所在了。
系统在大部分的情况下,延迟都比较低。到了 P99 甚至 P99.9 之后才会有很大幅度的变化,也就是常说的长尾延迟。这时可能就会有人不屑一顾的说 P99 而已,可以忽略。真的可以忽略么?
长尾延迟的危害
我们分别从代理的经典场景和新兴场景来看长尾延迟的危害。
Web 页面
Web 网站代理是很常见的经典代理场景,一个网站的页面经常由大量的资源组成。浏览器在渲染页面时,每个资源都会发起一个请求。下图(网图)列出了常见的 web 站点页面元素的数量(过去的数据,与现在的数据会有所出入)。
打开一个页面,遇到 P99 延迟的概率是 (1 - (.99 ^N)) * 100%
,得到的结果就是第三栏中的数据。页面元素最多的,遇到 P99 延迟的概率是 93.9%,最少的则是 26.7。
可见页面资源越多,遭遇 P99 延迟的概率也越高。
服务网格
服务网格的典型实现是通过与应用程序一起部署的可扩展网络代理(通常称为 sidecar 模型),来代理服务间的网络通信。引入了代理之后,原来的一次服务 RPC 调用又多了两跳。
一个请求的链路越长,经过的代理也就越多,遇到 P99 的概率也就越高。在高并发的场景下,延迟的影响尤为明显。
延迟的基准测试
如此来看对延迟的测量就很有必要了,在资源有效利用和可用性之间寻找平衡。制定 SLA 需求,评估系统的容量。
性能基准测试实践
在正式测试之前,我们先确定了本次测试的原则:
基准测试:基于测试的目标--引入了代理之后延迟的百分比分布--进行基准测试,与未使用代理进行对比,并测试多种场景。
可重复:测试过程中需要对配置等条件进行不断地调整,需要多轮的测试并对比结果。
可量化:在测试过程中进行设备的全方位的监控,对观测的结果可以进行量化、对比。
自动化:版本更新迭代后,测试更容易开展,进行自动化的测试,增加测试的轮次。
测试环境
AWS c5.large 2vCPU/4Gib
OS Ubuntu 20.04 TLS
3 台虚拟机分别作为 client(负载生成)、proxy、server(上游服务)
测试工具
这次测试我们对比了几种的不同工具。首先是负载生成器,也就是 client 端:
fortio:有命令行工具和服务端模式;服务端模式提供 web 用户界面和 REST API;延迟分布精度更高 99.9;可以固定 qps;结果图形化。
wrk:支持多线程和 Lua 脚本,使用 C 开发,没有 gc。wrk2 支持固定 qps 以及更高的精度 99.9999%。
ab:适合测试短连接,但没有延迟数据。
后端服务我们也进行了筛选,在 Nginx、Hashicorp Http Echo、Pipy 之间经过对比最终选择了使用 Pipy 运行 tutorial/02-echo/hello.js 作为上游服务。详细的对比结果可以参考这篇 BENCHMARK : Pipy as Echo server。
测试场景
我们设计了 4 个场景进行测试,尽量去模式真实环境可能出现的情况。
不同的负载压力:模拟不同的 RPS 场景:1000、2000、5000、10000 RPS 下请求的延迟百分比分布,同时测试不使用代理时的延迟分布。
不同 Payload:现实中请求的 payload 也各不相同。通过这个场景的测试模拟不同 payload:1KB、100KB、1MB 时的延迟分布,也同样测试了不使用代理时的延迟。
不同的连接数:在其他设置不变的情况,测试不同连接数对延迟分布的影响,比如 16、32、48、64、128。
负载均衡:这个场景主要测试代理负载均衡的性能,通过调整后端服务的副本数量,验证在增加系统容器的情况下的延迟分布。
更多协议:这是个比较特别的场景,因为 Pipy 支持更多的协议,比如 Dubbo、MQTT 等协议。我们加入了 MQTT 的测试,分别测试客户端连接、消息发送和订阅。(由于结果量化的问题,还未找到比较好的呈现方式。对此有经验的同学,可以给些建议)。
结果分析
经过测试,在引入了 Pipy 代理之后延迟只有小幅度的增加,并且在多种场景下延迟的分布成线性增长,没有大幅度的变化。
为了验证 Pipy 对延迟的优化,我们还增加了一个场景:使用 Pipy 代理 Java 服务与直接访问服务进行了对比。结果是使用了代理后会延迟降低 QPS 提升,有着更平稳的延迟分布。因为代理与 Java 服务间是长连接,Pipy 的网络接入能力,要大幅的优于 Java 网络能力,相当于给一个电器在插座上增加了一个稳压器。
下面是更多的场景测试结果。
测试结果
不同 RPS 下使用 Pipy 代理和直接访问对比
1000 RPS
2000 RPS:
5000 RPS:
10000 RPS:
使用代理时不同 RPS 的对比
不同 payload 下的对比
不同连接数下的对比
负载均衡不同后端实例数
不使用代理和 1、2、3 个后端实例时的延迟分布对比
版权声明: 本文为 InfoQ 作者【Flomesh】的原创文章。
原文链接:【http://xie.infoq.cn/article/c7352a669e172e822103a7e75】。文章转载请联系作者。
评论