尽管随着业界发展,处理器速度、内存大小以及I/O执行速度在快速增长,但I/O操作的吞吐量和响应时间仍然比内存访问操作要慢得多。此外,由于很多
工作负载都涉及到I/O操作,磁盘I/O很容易成为系统的瓶颈。因此,磁盘读写性能往往是
性能测试中一向需要考量的环节。
本次测试目标
本次磁盘性能测试对宿主机和各个规格云主机的磁盘性能做出加压。并重点关注云主机之间的互相影响,以及云主机与宿主机之间的影响。
根据这个思路,设计以下四个测试点。
测试点一:单独测试各规格云主机的性能。一来将测试结果作为基准数据,二来通过对比IOPS与磁盘空间的比例关系来验证磁盘QoS是否起作用。
测试点二:设计宿主机磁盘使用率成梯度负载,测试一台云主机、多台云主机混合场景下的云主机磁盘性能变化。用于得出宿主机磁盘负载对其上云主机磁盘性能的影响。
测试点三:宿主机空闲,云主机之间的互相影响。一台云主机磁盘设计成梯度负载,测试另一台云主机的磁盘变化情况。
测试点四:多台云主机组合加压,使得宿主机的磁盘使用率呈现梯度,在这种场景下,测试宿主机磁盘性能。用于得出云主机磁盘压力对宿主机磁盘性能的影响。
设计
测试用例时,应当时刻记住测试目的。先想好要得到什么样的结果,要得到什么样的对比,然后再有针对性的设计用例。做对比时,要保证只有一个参数再变动,如此才能得出这个参数对结果的影响。
工具选取与调研
考虑到
用例设计中的各种场景以及想要掌握的资源指标,最后选取了Fio作为本次测试的工具。Fio是一个用来对硬件I/O进行
压力测试和验证的工具。支持13种不同的I/O引擎,包括:sync, mmap, libaio, posixaio, SG v3, splice, null, network, syslet, guasi, solarisaio 等。
在Fio中,可以设置的选项有:
读写方式:随机读、随机写、顺序读、顺序写、随机读写、顺序读写。
文件大小:Fio进行I/O操作时使用的文件大小。
运行时间:一次测试执行的时间,在该时间段内,Fio将不断执行I/O操作。
混合场景读写比例:如果指定为读写操作(读与写操作都有),那么可以指定读与写占的时间比例。
线程数:指定多线程同时执行相同的测试任务。
Fio输出结果中含有iops、延迟时间、磁盘占用率等指标数据。
在本次测试中,通过指定Fio的rate_iops参数,即限定云主机读写的负载,来达到用例中设计的组合场景。
在使用Fio时,可以通过设定job文件,可以实现多条访问规则的顺序执行,进而缩减命令行中的选项长度。
一个job文件可以控制产生特定数目的线程和文件。典型的job文件有global段,一个或多少job段。
运行时,fio从文件读这些参数,做处理,并根据这些参数描述,启动这些仿真线程/进程。
运行job的方式: fio job_file
job文件采用经典的ini文件,[]中的值表示一项job的名称。
监控指标的确定
磁盘I/O的性能经常基于吞吐率和延迟来评估。磁盘驱动器对大数据量顺序传输的处理常常优于小数据量随机传输操作。对于磁盘的监控指标,主要集中在以下三个方面:
测试工具Fio统计的指标:iops,bps(传输速度),延迟时间。
系统cpu相关的指标:%usr,%sys,%iowait,中断次数,上下文切换次数。特别关注cpu0的使用情况。
系统磁盘I/O相关的指标:tps,await,svctm,%util。
上述各项指标含义如下:
IOPS:每秒钟处理的磁盘IO次数,由fio工具统计得出。
BPS:每秒钟处理的数据量大小,由fio工具统计得出。
延迟时间:
%usr:在用户级别运行所使用的CPU的百分比,由mpstat命令统计得出。
%sys:在系统级别(kernel)运行所使用CPU的百分比,由mpstat命令统计得出。
%iowait:因IO导致的进程等待,由mpstat命令统计得出。
中断:CPU中断次数,由vmstat命令统计得出。
上下文切换:CPU的控制权由运行任务转移到另外一个就绪任务时所发生的事件次数,由vmstat命令统计得出。
tps:每秒从物理磁盘I/O的次数,由iostat命令统计得出。
await:从设备流出的平均I/O请求时间,包括请求在队列和服务时的时间,由iostat命令统计得出。
svctm:平均I/O请求的服务时间,由iostat命令统计得出。
磁盘util%:磁盘利用率,由iostat命令统计得出。
测试过程
一、测试脚本的准备与验证
1.编写运行在云主机上的测试脚本
该脚本主要用于触发Fio进行测试,并制定log文件的存放路径。
2.将测试脚本及监控脚本拷贝至云主机
为了让测试过程尽可能自动化,在宿主机上将必要的文件分发到特定云主机上执行。需要的文件有测试脚本及负责监控的脚本。
3.ssh远程执行云主机上脚本
宿主机上通过ssh命令使云主机上测试脚本运作,并触发监控脚本对资源使用情况进行记录。
4.收集结果数据拷贝回宿主机
云主机上测试结束后,统一将各个轮次结果拷贝回宿主机归档,便于后续集中处理。
二、指标监控的实现
使用Perfease进行资源监控。 工具介绍链接:http://doc.hz.netease.com/pages/viewpage.action?pageId=16782036
三、测试结果的收集与整理
使用monitor.sh会将测试过程中所有的指标数据统计并保存到文件中。而为了保证监控数据的有效性,监控的时效往往略小于真实测试时间。此外专门编写了脚本来计算各指标的平均值,但将各轮测试的结果挑选出来放进报告中颇为费时。
而在整理数据的过程中,可能会遇到一些问题,例如同一用例跑两轮,两轮结果误差较大。当误差超过5%时,基本可以认定其中有一组数据无效。需要再跑一轮测试进行验证。
还有可能会发现,结果数据是准确的,但与对应场景预期的结果不符。这种情况可能是脚本参数设置不对,也有可能暴露了其他问题。需要对这种情况需要找开发了解相关背景信息,进而定位原因。
测试结论与总结
针对四个测试点的测试目的分别对测试结果进行提炼总结,结果与测试前的预期相符:
通过测试不同规格的云主机磁盘性能,各云主机iops比例与云主机磁盘空间比例相近,可以验证磁盘QoS起了作用。
随着宿主机磁盘负载增加,云主机iops快速下降;await与svctm差值增大,表明IO在请求队列中的时间增加;%iowait增大,cpu等待io时间变长。
宿主机磁盘空闲时,单台云主机磁盘负载增加,对其他云主机的磁盘性能影响很小。多台云主机负载增加时,其他云主机IO等待时间变长。
随着云主机磁盘负载增加,宿主机iops减少,await与svctm差值增大,说明IO请求在队列中时间增加。
预测试的重要性
预测试是指在正式测试之前对基本功能的一个基本验证。在这个过程中进行一些探索和验证,小规模的模拟正式测试来提前暴露一些问题,最终降低测试成本与风险。
这几个月下来的工作给我的体会是,性能测试过程似乎具备这样的特点:
测试工具需要设置多项参数来实现业务规模、场景负载等条件,各项指标间可能需要捆绑设置。即测试条件较复杂。
执行一个轮次下来往往时间很长,且大多数测试工具在执行完成后才会出具结果报告。即测试时间较漫长。
测试环境要保证前后一致。测试进程尽量独占整个系统,避免测试外的因素影响最终结果。
鉴于以上几点,如果因为测试脚本或测试环境的原因影响了结果,则会造成很大的时间损失。而引入预测试的目的,就是帮助我们提前检验测试脚本和测试环境,估量实际测试时间并发现需要人工介入的时刻。
此外,由于预测试帮助我们快速地领略了一遍测试过程的“生命周期”,正式测试时会更加得心应手。
及时发现问题
即便使用预测试来提前收集测试信息,但如何能够确保测试脚本和测试环境不出一点问题呢?很多时候我们发现不了错误是因为我们根本不知道自己犯了错误。
“实践是检验真理的唯一方法”,确保能发现的问题已经解决后,只好提心吊胆地开始正式测试了。
测试执行过程虽然漫长,但不能掉以轻心,时刻关注新鲜出炉的结果数据。若结果表现与预期不符,要及早定位问题:是系统误差,还是测试工具设置不对,还是数据收集时统计错了目标?
越早发现问题,越能节省成本。
向测试自动化靠拢
由于测试需要关注宿主机与云主机两方面的资源情况,监控数据需要分别收集。且测试用例设计了各种负载梯度,造成测试脚本和Fio的job文件偏多,需要对应分发到各个云主机上。这些都是繁琐但不可缺少的环节,为了防止人工操作带来的失误,在这些机械的操作尽可能地编写脚本令其自动实现。
自动化除了可以用来分发测试脚本、收集测试数据,还可以对新分配的云主机进行初始化,例如安装必要的工具包、更新软件源等等操作。
总而言之,自动化是一项提高效率,避免机械繁琐操作的好思路、好方法。磨刀不误砍柴工,花一点时间编写自动化工作的脚本,能为后续工作带来极大便利。