基准测试方法论
第1章 为什么需要基准测试
测量系统在给定的工作负载下会发生什么。
观察系统在不同压力下的行为,评估系统容量。
观察系统如何处理不同数据。
验证基于系统的一些假设,确认这些假设是否会符合实际情况。
重现系统中的某些异常行为,以解决这些异常。
测试系统当前的运行情况。如果不清楚当前系统的性能,就无法确认某些优化的效果如何。
模拟比当前系统更高的负载,以找出系统对着压力增加而可能遇到的扩展性瓶颈。
规划未来的业务增长。评估在项目未来的负载下,需要什么样的硬件,需要多大容量的网络,帮助降低系统升级和重大变更的风险。
测试应用适应可变环境的能力。可以发现系统在随机的并发峰值下的性能表现,或者不同配置的服务器之间的性能表现。也可以测量系统对不同数据分布的处理能力。
测试不同硬件、软件、操作系统配置。比如RAID 还是和RAID10更合适当前系统?从本地磁盘存储升级到SAN存储,对于随机写性能有什么帮助?Linux 2.4系列内核回避2.6系列的可扩展性更好么?升级软件版本能改善性能么?
证明新采购的设备是否配置正确。发现服务器硬件的错误配置。
第2章 测试何种指标
基准测试有两种主要的策略:一是针对整个系统的整体测试,另外是单独测试。这两种策略被称为集成式(full-stack)和单组件试(single-component)基准测试。
-
针对整个系统做集成式测试,原因主要有以下几点:
-
测试整个应用系统,包括Web服务器、应用代码、网络和数据库是非常有用的,因为用户关注的并不仅仅是某个应用本身的性能,而是应用整体的性能。
-
数据库并非总是应用的瓶颈,通过整体测试可以揭示这一点。
-
只有对应用做整体测试,才能发现各个部分之间的缓存带来的影响。
-
整体应用的集成式测试更能揭示应用的真实表现,而单独组件的测试很难做到这一点
有时候不需要了解整个系统的情况,而只需要关注单独应用的性能,至少项目初期可以这样做。
开始基准测试甚至是设计基准测试之前,需要先明确测试的目标。测试决定选择什么样的测试工具和技术,以获取精确而有意义的测试结果。可以将测试目标细化为一些列问题,比如“增加缓存是否能够带来性能提升?”
有时候需要用不同的方法测试不同的指标,比如针对延迟(latency)和吞吐量(throughput)就需要采用不同的测试方法
吞吐量指的是单位时间爱你内的事务处理数量。主要针对在线事务的吞吐量,非常适合多用户的交互式应用。常用测试单位是每秒事务数(TPS)和每分钟事务数(TPM)
这个指标用于测试任务所需的整体时间。根据具体应用,测试渐渐单位可能是微秒、毫秒、秒或分钟。根据不同的时间单位,可以计算出平均响应时间、最小响应时间、最大响应时间和所占百分比。最大响应时间通常意义不大,因为测试时间越长,最大响应时间可能越大。而其结果不可重复,每次测量可能得到不同的最大响应时间。因此,通常可以使用百分比响应时间(percentile response time)来代替最大响应时间。例如,如果95%的响应时间都是5毫秒,则表示人物的95%的时间都可以在5毫秒内完成。
使用图标有助于理解测试结果。
并发性是一个非常重要又经常被被误解和误用的指标。例如,它经常被表示成多少用户在同一时间浏览一个Web站点,经常使用的指标是有多少个回话。然而,HTTP协议是无状态的,大多数用户只是简单的读取浏览器上显示的信息,这并不等同于Web服务器的并发性。而且,Web服务器的并发性也不等同于数据库的并发性,而仅仅只表示回话存储机制可以处理多少数据的能力。Web服务器的并发性更准确的度量指标,应该任意时间有多少同时发生的并发请求。
在应用的不同缓解,都可以测量响应的并发性。Web服务器的高并发,一般会导致数据库的高并发,但服务器采用的语言和工具集对此都会有影响。注意不要将创建数据库链接和并发性搞混淆。
一个设计良好的应用,可以同时打开成百上千个数据库链接,但可能只有少数连接在执行。所以说,一个Web站点”同时有50000个用户“访问,却可能只有10~15个并发请求道数据库。
换句话说,并发性基准测试关注的是正在工作中的并发操作,或者是同时工作中的线程数或者连接数。当并发性增加时,需要测试吞吐量是否下降,响应时间是否边长,如果是这样,应用可能就无法处理峰值夜里。
并发性的测试完全不同于响应时间和吞吐量。它不想一个结果,而更像是设置基准测试的一种属性。并发测试通常不是为了测试应用能达到的并发度,而是为了测试应用在不同并发下的性能。
在系统的业务压力可能发生变化的情况下,测试可扩展性就非常重要了。简单的说,可扩展性指的是,给系统增加一倍的工作,在理想情况下,能够获得两倍的结果(即吞吐量增加一倍)。或者说,给系统增加一倍的资源(比如两倍的CPU),就可以获得两倍的吞吐量。当然,同时吸能(响应时间)也必须在可以介绍的范围内。大多数系统无法做到如此理想的线性扩展。随着压力的变化,吞吐量和性能都可能越来越差。
可扩展性指标对于容量规划非常有用,它可以提供其他基准测试无法系统的信息。比如系统是基于单个用户的响应时间测试(这是一个很糟糕的测试策略)设计的,虽然测试的结果很好,但并发度增加时,系统的性能有可能变得非常糟糕。而一个不断增加爱用户连接的情况下的响应时间测试则可以发现这些问题。
归根结底,应该测试那些对用户来说最重要的指标。因此应该尽可能的收集一些需求,比如,什么样的响应时间是可以介绍的,期待多少并发性,等等。然后基于这些需求来设计基准测试,避免目光短浅的只关注部分指标,忽略其他指标。
第3章 基准测试方法
-
使用真实数据的自己而不是全集。例如应用需要处理几百GB的数据,但测试只使用1GB数据;或者只使用当前数据进行测试,却希望模拟未来业务大幅增长后的情况。
-
使用错误的数据分布。例如使用均匀分布的数据测试,而系统的真实数据有很多热点区域(随机生成的测试数据通常无法模拟真实的数据分布)。
-
使用不真实的分布参数,假定所有用户的个人信息都会平均的读取。
-
在多用户的场景中,只做单用户的测试。
-
在单服务器上测试分布式应用。
-
与真实用户行为不匹配。例如Web页面中的”思考时间“。真实用户在请求道一个页面后,会阅读一段时间,而不是不停顿的一个接一个点击相关链接。
-
反复执行同一个查询。真实的查询时不尽相同的,这可能导致缓存命中率降低。而繁芜执行同一个查询,在某种程度上,会全部或者部分缓存结果。
-
没有检查错误。如果测试的结果无法得到合理的解释,比如一个本应该是很慢的查询突然变快了,就应该检查是否是有错误产生。基准测试后,一定要检查一下错误日志,这是基本要求。
-
忽略了系统预热(warm up)的过程。例如系统重启后马上进行测试。有时候需要了解系统重启后需要多长时间才能达到正常的系统容量,需要特别留意预热的时间。反过来说,如果想分析正常的性能,需要注意,基准测试在重启后马上启动,则缓存是冷的,没有数据,这时候即使测试的压力相同,得到的结果和缓存已经装满数据时是不同的。
-
使用默认的服务器配置。
-
测试时间太短。基准测试需要持续一定时间
只有避免了上述错误,才能走上改进测试质量的漫漫长路。
如果其他条件相同,就应该努力使测试尽可能的真实应用的情况。当然,有时候和实际情况晒为有些出入问题也不打。例如,实际应用服务器和数据库服务器分别部署在不同的机器。如果采用和实际部署完全相同的配置当然更真实,但也会引入更多变化,比如网路负载和速度。在单一节点上运行测试相对容易,在某些情况下结果也可以介绍,那么就在单一节点上进行测试。当然,这样的选择需要根据实际情况来分析是否合适。
规划基准测试的第一步是提出问题并明确目标。然后决定是采用标准的基准测试,还是设计专用的测试。
建立测试和结果文档化的规范,每轮测试都必须进行详细记录。文档规范可以很简单,可以采用电子表格或记事本,也可以是复杂的自定义数据库。需要记住的是,经常需要写一些脚本来分析结果,因此如果能够不用打开电子表格或者文本等额外操作是最好的。
执行基准测试时,需要尽可能的多手机测试系统的信息。最好为基准测试建立一个目录,并且没执行议论测试,都创建单独的子目录,将测试结、配置文件、测量指标、脚本和其他相关说明保存在其中。及时有些结果目前不需要,也应该保存下来。多余一些数据总比缺乏重要的数据摇号,二多余的数据以后或许用得着。需要记录数据包括系统状态和性能指标,诸如CPU使用率、磁盘I/O、网络流量、应用状态。
获得准确测试结果的最好办法,是回答一些基准测试的基本问题
-
是否选择了正确的基准测试?
-
是否为问题收集了相关主句?
-
是否采用了错误的测试标准(比如是否对一个I/O密集型应用,采用了CPU密集型测试标准)
接着,确认测试结果是否可重复性。每次重新测试前,确保系统状态是一致的。如果是非常重要的测试,需要每次测试都重启系统。如果测试过程修改数据或者schema,那么每次测试前,需要利用快照还原数据。在表中插入1000条和插入100万条记录,测试结果肯定不同。数据碎片度和磁盘上的分布,都可能导致测试时不可重复的。
要注意的因素很多,包括外部的压力、性能分析和监控系统、详细的日志记录、周期性作业。例如,测试过程中突然有cron定时作业启动,或者RAID卡启动了定时的一致性检查。需要确保基准测试过程中所需要的资源是专用于测试的。如果有其他额外的操作,会消耗网络带宽,或者测试基于的是其他服务器共享的SAN存储,那么得到的结果可能是不准确的。
每次测试中,修改的参数应该尽量少。如果必须要一次修改多个参数,那么可能会丢失一些信息。有些参数依赖其他参数,这些参数无法单独修改。有时候甚至没有意识到这些依赖,这给测试带来了复杂性。
基准测试通常需要运行多次。具体需要运行多少次看对结果的计分方式,以及测试的重要程序。一般取最好值或平均值,亦或5次测试中最好的三个值的平均值。
获得测试结果后,需要对结果进行分析,也就是把数字变成知识。最终的目的是回答在设计测试是的问题。理想情况下,莪可以一获得诸如”升级4核CPU可以在保持响应时间不变的情况下,获得超过50%的吞吐量增加“或者”增加索引可以使查询更滑“的结论。
简单有效的图形,就是将性能指标按照时间顺序绘制。通过图形可以理解发现一些问题,而这些问题再原始数据中却很难被注意到。或许你会坚持看测试工具打印出来的平均值或其他汇总过的信息,但平均值有时候是没有用的,他会掩盖掉一些实际情况。
第4章 基准测试工具
- ab
只能测试单一域名
- http_load
可以测试多个域名,并随机选择进行测试
- JMeter
更复杂,可以设置参数众多,能够更加灵活的monitor真实用户访问,并有绘图接口、还可以对测试进行记录,离线重演测试结果。支持压测多种不同应用。
- siege
能够模拟比http_load更大的负载,并支持延迟、随机等特性,可以更好的模拟真实用户请求,仅用于Web服务测试。
- TPCC-MySQL
Percona出品,主流MySQL压测
- sysbench
主流MySQL压测,支持Lua脚本,同时还支持操作系统和硬件的硬件测试。
第5章 总结
基准测试并不是仅仅用来解决业务问题的一种时间,也是一种很好的学习方法。学习如何将问题分解成可以通过基准测试来获得答案的方法,就和数学课上从文字题目中推到出方程式一样。首先正确的描述问题,然后选择合适的基准测试来回答问题。设置基准测试的持续时间和参数,运行测试,收集数据,分析结果数据。
如果经常执行基准测试,那么指定一个原则很有必要。选择合适的测试工具深入的学习。可以建立一个脚本库,用于配置基准测试,收集输出结果、系统性能和状态,以及分析结果。使用一种熟悉的绘图工具gnuplot或者R,不用浪费时间使用电子表格,他们即笨重,速度又慢。尽量早和多的使用绘图的方式,来发现基准测试和系统中的问题和错误,你的眼睛是比任何脚本和自动化工具都更有效的发现问题的工具。
压测工具 - Siege
安装方法
安装epel源(aliyun)
yum install siege
下载位置
http://download.joedog.org/siege/
wget -P /opt http://download.joedog.org/siege/siege-latest.tar.gz
安装
tar xzf siege-4.0.2.tar.gz
cd siege-4.0.2
./configure
make && make install
常用参数
-c,并发用户,默认为10
-r, 运行测试次数。
-t, 测试时间
核心参数
-d,建议配置为“1”,每个请求前的随机延迟
-i,随机点击URL。
-f,选择一个特定的URLS FILE。
-b,暴力测试,无延迟,查看某个压力下,资源的变化情况
压测控制参数
-q,关闭并禁止输出。
-l,--log [= FILE] LOG到FILE。如果没有指定FILE,则使用默认值:PREFIX/var/siege.log
定制化参数
-H,--header =“text”添加一个头来请求(可以是很多)
-A,--user-agent =“text”请求中设置用户代理
-T,--content-type =“text”在请求中设置Content-Type
如何使用1台24核,16GB内存的服务器,模拟20000并发请求?
- 使用Centos7系统
- 做好内核中网络部分的优化
- 做好系统文件描述符的优化
- 建立10个用户(a...j)
调整配置
每个用户下运行一次siege,会在用户目录下产生~/.siege/siege.conf的配置文件,该文件中需要调整2个限制参数
- 出现多少次错误时停止,不包含404(按需调整)
failures - 最大单进程并发数量,默认25
concurrent = 5000
例:20W请求,多长时间能够处理完成,并且没有错误产生
siege -c 1000 -r 20 -i
10用户,每个用户并发1000,循环20次
主要关注总时常、响应时间、平均每秒完成请求、错误数
例:20000并发,运行10分钟,观察服务器和应用的运行情况
siege -c 2000 -t 10m -b
10用户,每个用户2000并发,运行10分钟
主要关注响应时间、平均每秒完成请求、平均每秒传送数据、实际最高并发
系统资源监控使用dstat
dstat -t -a -l -m --tcp --top-cpu --output /tmp/145-2c10240-15000.txt
Web服务器监控
Zabbix监控状态页或内部运行情况
- 压测后卡住,10个用户,有些压测进程压测完成后退出失败
取可用结果,平均后乘以10,作为压测结果,总耗时和响应时间,只平均不乘10
- 自身资源不足
系统优化
实际使用时,压测比较消耗内存
- Web服务器处理失败(到达处理瓶颈)
[error] socket: -872327424 connection timed out.: Connection timed out
[error] socket: read error Connection reset by peer sock.c:539: Connection reset by peer
举例:压测Nginx,15000并发,页面大小150kB,压缩后800字节
Nginx配置
gizp on
worker_processes=2
worker_connections 10240
用户a
Transactions: 10454 hits
Availability: 100.00 %
Elapsed time: 30.05 secs
Data transferred: 6.89 MB
Response time: 1.94 secs
Transaction rate: 347.89 trans/sec
Throughput: 0.23 MB/sec
Concurrency: 674.49
Successful transactions: 11805
Failed transactions: 0
Longest transaction: 16.98
Shortest transaction: 0.00
用户b
Transactions: 21462 hits
Availability: 100.00 %
Elapsed time: 30.06 secs
Data transferred: 13.32 MB
Response time: 0.74 secs
Transaction rate: 713.97 trans/sec
Throughput: 0.44 MB/sec
Concurrency: 528.73
Successful transactions: 22830
Failed transactions: 0
Longest transaction: 8.57
Shortest transaction: 0.00
备注:取5个用户,平均后乘10。但总用时,响应时间只平均,不乘10
Trans | Elap Time | Data Trans | Resp Time | Trans Rate | Throughput | Concurrent |
---|---|---|---|---|---|---|
150404 | 30.32 | 95.54 | 1.262 | 5008 | 3.16 | 5788.76 |
压测工具 - http_load
安装方法
安装
tar xf http_load-09Mar2016.tar.gz
cd http_load-09Mar2016
make && make install
-parallel 简写 -p : 含义是并发的用 户进程数。
-fetches 简写 -f : 含义是总计的访 问次数
-rate 简写 -r : 含义是每秒的访 问频率
-seconds 简写 -s : 含义是总计的访问 时间
50000 fetches, 150 max parallel, 2.13658e+08 bytes, in 29.0605 seconds
#说明在上面的测试中运行了50000个请求,最大的并发进程数是150,总计传输的数据是2.13658e+08 bytes,运行的时间是29.0605秒
4273.15 mean bytes/connection
#说明每一连接平均传输的数据量 2.13658e+08/50000
1720.55 fetches/sec, 7.35216e+06 bytes/sec
#说明每秒的响应请求为1720.55,每秒传递的数据为7.35216e+06 bytes/sec
msecs/connect: 1.98612 mean, 1003.53 max, 0.418 min
#说明每连接的平均响应时间是1.98612 msecs,最大的响应时间1003.53 msecs,最小的响应时间0.418 msecs
msecs/first-response: 82.6688 mean, 7222.38 max, 0.873 min
#第一个请求情况
HTTP response codes:
code 200 -- 41651
code 404 -- 8349
1720.55 fetches/sec 美妙响应请求数
msecs/connect 每秒请求时间