在前面几篇文章中我们更多的描述了从代码到发布的持续交付的过程,但是在很多复杂的系统上线前都得会进行性能测试,通过性能测试来进行容量规划,系统的瓶颈检测,可靠性检查,高负载的强度测试,从而更好的保证业务的持续交付流程。
还记得第一次听说性能测试这个词是在大学二年级,刚刚进入实验室,老师将一本Load Runner的书籍放在桌子上,告诉我用这个工具测试下学校课程网站的性能。相当长的时间内,对性能测试的理解就是用一个类似Load Runner的工具,然后通过工具得出一些指标,就可以交工了。但是实际上性能测试是一类测试的统称,而压力测试是最常见的性能测试的一种,性能测试(广义)还包括负载测试、并发测试、可靠性测试等等。
在本文中,今天主要讨论的是压力测试、负载测试与并发测试,对于大部分的应用来讲,这三种测试已经可以满足基本的需求了。
压力测试、负载测试、并发测试是三个非常容易混淆的概念,在很多性能测试工具中会同时提供这几种测试的能力,这也使得非常多的开发者认为性能测试就是压力测试。
负载测试的目标是确定并确保系统在超出最大预期工作量的情况下仍能正常运行。此外,负载测试还要评估性能特征。例如,响应时间、事务处理速率和其他与时间相关的方面。在一些高并发的场景中,负载测试是测试在极限情况下系统的容量的最常见的做法,通过不断对系统添加压力,直到系统出现某些资源耗尽,例如CPU或者网络带宽。通常情况下要求被测系统与线上系统的环境保持一致,如果不能保持一致,那么可以通过模拟拟合的方式进行估算。举一个简单的例子,如果线上的配置64C64G的ECS,但是我们目前只能找到2C2G、4C4G、8C8G的ECS,那么我们可以在不同的线性配置上面进行负载测试,并通过得出的负载曲线进行估算。
压力测试也叫强度测试,是指系统在预设的负载范围内,例如CPU满载、内存饱和等情况下,系统对于测试场景的反应能力,和负载测试不同的是,压力测试并不是倾向于探寻超出预期的极限上限,更多的是在容量规划内,去保证系统的可用性。所以通常情况下会先进行负载测试,再根据负载测试的结果,指定压力测试的方案。
并发测试是通过模拟用户的并发访问,测试多个用户并发访问同一个应用、同一个模块甚至同一条记录等等场景下,业务逻辑锁是否有泄漏、内存是否有泄漏、资源是否有互锁等等。这种测试方式更倾向于发现实际运行中系统隐藏的问题。
微服务架构成为了越来越多开发者进行系统拆分与系统重构的第一选择,虽然微服务在开发模式、迭代速度等方面有非常大的优势,但是微服务也带来了很多的挑战。当微服务遇到性能测试的时候,会有哪些不同呢。
在一个单体的应用中,性能测试非常简单,只需要设定测试规则以及相应的测试端点,剩下大部分只需要通过测试工具即可完成性能测试。但是当一个单体应用拆分成了多个微服务的时候,如果我们依旧只用黑盒的方式进行性能测试,从系统的最外侧的端点进行测试,那么就会像一个有短板的木桶一样,这个系统中,承载能力最低的微服务就会成为系统的测试结果的基线。面对微服务架构的挑战,性能测试也应该是更细粒度的,应该是既有自顶向下的类黑盒测试,也应该有对每一个微服务的性能测试。而且还可以通过类似zipkin这种分布式跟踪的工具实现微服务系统中瓶颈的子服务,具体的实现在本文中就不过多的赘述了。
性能测试工具有非常多的选择,比如大名鼎鼎的apache ab、Jmeter、gatling等等。在本文中我们的选择是Tsung,Tsung是基于Erlang构建一个分布式的性能测试工具,支持HTTP/HTTPS、UDP、MQTT、WebSocket等协议,支持分布式的压力测试,支持生成报表与结果,是非常适合容器场景的一个压力测试的选择。
Tsung本身是一个基于Erlang OTP的主从结构的系统,主节点可以产生压力并分发任务,从节点可以接收任务,并产生压力。Tsung的使用方式非常简单,只需要一个XML的配置文件,即可运行。下面我们来看一个简单的配置文件:
大家只需要记住几个关键的字段的含义即可
| 字段 | 含义 |
| ---- | ---- |
|client|是执行任务产生压力的执行者,通常配置hostname或者IP|
|servers|配置压测的地址|
|load|负载相关的设置|
|options|配置压测内容相关的选项,例如session或者user agent等|
下面我们做一个最简单的负载测试,只跑一个Tsung的master节点,对一个特定的URL进行负载测试。
compose文件如下:
tsung-single:
image: "registry.cn-hangzhou.aliyuncs.com/ringtail/tsung:v1.0"
volumes:
- '/root/sample.xml:/root/.tsung/tsung.xml'
- '/var/lib/docker/tsung:/root/.tsung/log'
labels:
aliyun.routing.port_8091: tsung
command: single
sample.xml的配置如下:
应用部署完成,点击暴漏的路由地址
访问Tsung提供的web控制台,其中Active nodes的数目为1,目前只有master一个节点。
点击右上角的菜单栏,可以查看更详细的图表与数据
只使用Master一个节点进行压力可能对于某些场景来讲是不够用的,我们可能需要分布式的性能测试来开启洪荒之力。对于Tsung来讲,分布式压力测试是非常简单的一件事情。只需要让从节点可以从主节点进行SSH免登,并且从节点上面安装Tsung即可,主节点只需要添加一行代码即可完成一个分布式的配置就是在clients的下面加上从节点的配置即可。
要做到主节点与从节点SSH免登打通,需要生成一对SSH key pair。
//在本地执行,两个引号表示无需输入密码
ssh-keygen -t rsa -P""
命令执行完了可以发现生成了一对ssh秘钥对,id_rsa与id_rsa.pub,我们将生成的私钥通过volume的方式挂载到主节点中,将公钥通过环境变量的方式传递到从节点中,compose文件如下:
tsung-master:
image: "registry.cn-hangzhou.aliyuncs.com/ringtail/tsung:v1.0"
volumes:
- '/mnt/acs_mnt/ossfs/cs-volume/sample.xml:/root/.tsung/tsung.xml'
- '/var/lib/docker/tsung:/root/.tsung/log'
- '/mnt/acs_mnt/ossfs/cs-volume/id_rsa:/root/.ssh/id_rsa'
environment:
- DISABLE_HOST_CHECK= true #免用户输入yes
labels:
aliyun.routing.port_8091: tsung
command: "master"
links:
- "tsung-slave:tsung-slave" #可不适用link,直接使用hostname
tsung-slave:
image: "registry.cn-hangzhou.aliyuncs.com/ringtail/tsung:v1.0"
command: "slave"
environment:
- AUTHORIZED_KEYS=<公钥内容> #cat ~/.ssh/id_rsa.pub
最后将从节点的HOSTNAME配置到sample.xml中。
进行部署,开始测试,可以发现Active nodes的数目变成了2个,也提供了更强大的压力。
性能测试不是目的,更多的是为了在上线前进行问题的发现与性能的调优。常见的一个标准流程是先进行负载测试,然后根据负责测试的结果,进行压力测试的场景指定,进行容量假设与容量规划。有的系统还会进行并发测试。常见的系统调优方式有USE方法、随机变动讹方法、Ad Hoc核对清单法等等。具体的内容在本文中就不过与赘述了,只需要记住性能测试的目的是为发现问题、调优系统、容量规划,而不是单纯的使用一个工具,用尽洪荒之力得到一个没有业务场景与支持的数据,更多的是要用性能测试提供数据,并根据特定场景下的数据进行决策。
在本文中我们只是讨论了Tsung的最基本的用法, 包括单点负载测试与分布式负载测试,阿里云容器服务针对微服务的场景提供了非常多的能力,在下一篇文章中,我们会针对微服务场景下性能测试进行分析,提供更有针对性的性能测试与调优的方案。
<在做性能测试前需要知道什么> 地址
<在做性能测试之后需要知道什么> 地址
<性能之巅 洞悉系统、企业与云计算> Brendan Gregg
SSH免登 github地址
Tsung的Dockerfile ps://github.com/ringtail/tsung-image" target="_blank">github地址