请注意系统版本 !
概述
性能测试 是通过自动化的测试工具模拟多种正常、峰值以及异常负载条件来对系统的各项性能指标进行测试。负载测试和压力测试都属于性能测试,两者可以结合进行。通过负载测试,确定在各种工作负载下系统的性能,目标是测试当负载逐渐增加时,系统各项性能指标的变化情况。压力测试是通过确定一个系统的瓶颈或者不能接受的性能点,来获得系统能提供的最大服务级别的测试。
外部指标
从外部看,主要关注三个指标
- 吞吐量:每秒钟系统能够处理的请求数、任务数。
- 响应时间:服务处理一个请求或一个任务的耗时。
- 错误率:某批次请求中失败或发生错误的请求比例。
互相影响关系如下:
响应时间的指标取决于具体的服务返回的数据有效周期,实时性。对于响应时间的统计,应从均值、.90、.99、分布等多个角度统计,而不仅仅是给出均值。
吞吐量的指标受到响应时间、服务器软硬件配置、网络状态等多方面因素影响。
吞吐量越大,响应时间越长。
服务器硬件配置越高,吞吐量越大。
网络越差,吞吐量越小。
在低吞吐量下的响应时间的均值、分布比较稳定,不会产生太大的波动。
在高吞吐量下,响应时间会随着吞吐量的增长而增长,增长的趋势可能是线性的,也可能接近指数的。当吞吐量接近系统的峰值时,响应时间会出现激增。
错误率和服务的具体实现有关。通常情况下,由于网络超时等外部原因造成的错误比例不应超过5%%,由于服务本身导致的错误率不应超过1% 。
内部指标
从系统的角度看,性能测试主要关注CPU、内存、负载、网络、磁盘IO等
CPU
后台服务的所有指令和数据处理都是由CPU负责,主要有如下几个维度的统计指标:
- us:用户态使用的cpu时间百分比
- sy:系统态使用的cpu时间百分比
- ni:用做nice加权的进程分配的用户态cpu时间百分比
- id:空闲的cpu时间百分比
- wa:cpu等待IO完成时间百分比
- hi:硬中断消耗时间百分比
- si:软中断消耗时间百分比
- us & sy:大部分后台服务使用的CPU时间片中us和sy的占用比例是最高的。
同时这两个指标又是互相影响的,us的比例高了,sy的比例就低,反之亦然。
在使用多核CPU的服务器上,CPU 0负责CPU各核间的调度,CPU 0上的使用率过高会导致其他CPU核心之间的调度效率变低。因此测试过程中CPU 0需要重点关注。
-
ni:每个Linux进程都有个优先级,优先级高的进程有优先执行的权利,这个叫做pri。进程除了优先级外,还有个优先级的修正值。这个修正值就叫做进程的nice值。一般来说,被测服务和服务器整体的ni值不会很高。如果测试过程中ni的值比较高,需要从服务器Linux系统配置、被测服务运行参数查找原因。
-
id:线上服务运行过程中,需要保留一定的id冗余来应对突发的流量激增。在性能测试过程中,如果id一直很低,吞吐量上不去,需要检查被测服务线程/进程配置、服务器系统配置等。
-
wa:磁盘、网络等IO操作会导致CPU的wa指标提高。通常情况下,网络IO占用的wa资源不会很高,而频繁的磁盘读写会导致wa激增。如果被测服务不是IO密集型的服务,那需要检查被测服务的日志量、数据载入频率等。
-
hi & si:硬中断是外设对CPU的中断,即外围硬件发给CPU或者内存的异步信号就是硬中断信号;软中断由软件本身发给操作系统内核的中断信号。通常是由硬中断处理程序或进程调度程序对操作系统内核的中断,也就是系统调用(System Call)。在性能测试过程中,hi会有一定的CPU占用率,但不会太高。对于IO密集型的服务,si的CPU占用率会高一些。
在异步框架中,CPU本身是不会被IO阻塞的,主要关注点:
- 数据处理:
字符串操作(尝试流)
内存操作(内存池)
数据结构设计(红黑树换HASHMAP)
- 并发的处理:
锁的临界区减少(仅在必要时加小粒度锁)
队列化(无锁)
- 计算、存储、网络三者要做到平衡:
合理的将网络、计算的开销减小,增大存储的开销(缓存),大部分计算、网络的瓶颈都可以用增大存储来解决,但要有度。
更合理的调度(docker、云化)
内存
对内存监控的主要目的是检查被测服务所占用内存的波动情况。top命令内存相关参数解析如下:
- VIRT:进程所使用的虚拟内存的总数。它包括所有的代码,数据和共享库,加上已换出的页面,所有已申请的总内存空间
- RES:进程正在使用的没有交换的物理内存(栈、堆),申请内存后该内存段已被重新赋值
- SHR:进程使用共享内存的总数。该数值只是反映可能与其它进程共享的内存,不代表这段内存当前正被其他进程使用
- SWAP:进程使用的虚拟内存中被换出的大小,交换的是已经申请,但没有使用的空间,包括(栈、堆、共享内存)
- DATA:进程除可执行代码以外的物理内存总量,即进程栈、堆申请的总空间
测试过程中主要监控RES和VIRT,对于使用了共享内存的多进程架构服务,还需要监控SHR。
###LOAD(服务器负载)###
系统负载指运行队列的平均长度,也就是等待CPU的平均进程数
- 从服务器负载的定义可以看出,服务器运行最理想的状态是所有CPU核心的运行队列都为1,即所有活动进程都在运行,没有等待。这种状态下服务器运行在负载阈值下。
- 通常情况下,按照经验值,服务器的负载应位于阈值的70%~80%,这样既能利用服务器大部分性能,又留有一定的性能冗余应对流量增长。
- Linux提供了很多查看系统负载的命令,最常用的是top和uptime
- top和uptime针对负载的输出内容相同,都是系统最近1分钟、5分钟、15分钟的负载均值
- 统负载阈值的命令如下
- 在性能测试过程中,系统负载是评价整个系统运行状况最重要的指标之一。通常情况下,压力测试时系统负载应接近但不能超过阈值,并发测试时的系统负载最高不能超过阈值的80%,稳定性测试时,系统负载应在阈值的50%左右。
###网络###
网络监控主要包括网络流量、网络连接状态的监控。
- 网络流量监控
- 可以使用nethogs命令。该命令与top类似,是一个实时交互的命令。
- 在后台服务性能测试中,对于返回文本结果的服务,并不需要太多关注在流量方面。
- 网络连接状态监控
- 性能测试中对网络的监控主要是监控网络连接状态的变化和异常。对于使用TCP协议的服务,需要监控服务已建立连接的变化情况(即ESTABLISHED状态的TCP连接)。对于HTTP协议的服务,需要监控被测服务对应进程的网络缓冲区的状态、TIME_WAIT状态的连接数等。Linux自带的很多命令如netstat、ss都支持如上功能。
磁盘IO
如果被测服务对磁盘读写过于频繁,会导致大量请求处于IO等待的状态。可以用iostat命令来监控磁盘状态,注意需要加上-x参数, 获得系统运行有价值的统计数据。
- tps:该设备每秒的传输次数。“一次传输”意思是“一次I/O请求”。多个逻辑请求可能会被合并为“一次I/O请求”。“一次传输”请求的大小是未知的
- kB_read/s:每秒从设备(driveexpressed)读取的数据量,单位为Kilobytes
- kB_wrtn/s:每秒向设备(driveexpressed)写入的数据量,单位为Kilobytes
- kB_read:读取的总数据量,单位为Kilobytes
- kB_wrtn:写入的总数量数据量,单位为Kilobytes
- rrqm/s:每秒这个设备相关的读取请求有多少被Merge了(当系统调用需要读取数据的时候,VFS将请求发到各个FS,如果FS发现不同的读取请求读取的是相同Block的数据,FS会将这个请求合并Merge)
- wrqm/s:每秒这个设备相关的写入请求有多少被Merge了
- await:每一个IO请求的处理的平均时间(单位是毫秒)
- %util:在统计时间内所有处理IO时间,除以总共统计时间。例如,如果统计间隔1秒,该设备有0.8秒在处理IO,而0.2秒闲置,那么该设备的%util = 0.8/1 = 80%,该参数反映设备的繁忙程度。
常见性能瓶颈
- 吞吐量到上限时系统负载未到阈值:一般是被测服务分配的系统资源过少导致的。可以从ulimit、系统开启的线程数、分配的内存等维度定位问题原因
- CPU的us和sy不高,但wa很高:如果被测服务是磁盘IO密集型型服务,wa高属于正常现象。但如果不是此类服务,最可能导致wa高的原因有两个,一是服务对磁盘读写的业务逻辑有问题,读写频率过高,写入数据量过大,如不合理的数据载入策略、log过多等;二是服务器内存不足,服务在swap分区不停的唤入唤出。
- 同一请求的响应时间忽大忽小:在正常吞吐量下发生此问题,可能的原因有两方面,一是服务对资源的加锁逻辑有问题,导致处理某些请求过程中花了大量的时间等待资源解锁;二是Linux本身分配给服务的资源有限,某些请求需要等待其他请求释放资源后才能继续执行。
- 内存持续上涨:在吞吐量固定的前提下,如果内存持续上涨,那么很有可能是被测服务存在明显的内存泄漏,需要使用valgrind等内存检查工具进行定位。
举例
性能测试的需求背景三种情况:
- 第一种是现网出现性能问题,项目组专门进行了性能改造。比如修改的某个接口,由原来的同步调用修改成了异步,又或者是更换了新的api,由tcp协议修改为udp协议,为了保证新替换的api的可靠性,都需要进行性能测试
- 第二种是一个新做的系统,运营人员需要全面的把脉,了解该系统的处理能力。
- 第三种是随着请求量的快速增长,而该系统却从未做过性能测试,项目组担心系统在可预见的短期会扛不住,所以要求测试人员对该进行全面的性能测试,给出一份参考数据
- 第四种是线上系统发生性能故障,需要对系统性能弱项进行摸底排查
一个完整的后台服务性能测试流程如下
测试前准备:
- 系统需求分析:
- 系统所期望的性能指标:现网指标,需求指标
- 组网以及网间各个系统之间的通信形式:tcp/upd,网关,鉴权
- 系统的各个逻辑分支:核心业务逻辑,性能瓶颈业务
- 系统内部模块的组合:业务模块,基础模块
- 确定性能测试指标
- 设计性能测试用例:
- 选定最合适的逻辑分支进行测试。
- 设计最有针对性,最有效的测试用例。
- 请教有经验的性能测试工程师和开发工程师。
- 测试环境的准备:
- 数据:大数据量以及数据的多样性往往是模拟的难点。大数据量需要自己写脚本将数据库填充到一定的程度,如果要求高的话,甚至可以采用从现网导数据的方法。多样性往往比较难以实现,需要了解现网的数据多样性以及比例,达到模拟的效果
- 网络时延:这个和公司的IDC机器管理很相关.我之前一直以为所有的测试机器都在一个IDC,后来发现其实不然,我们的测试机器也和运营机器一样,分布在不同的IDC,而我们在挑选机器部署时,需要先了解一下现网运营机器之间的网络时延。这在测试整个一条逻辑分支的性能时尤为重要。
- 配置:日志级别的配置,线程或进程的个数,如果条件允许,配置可以升级到机器的硬件的配置,如果可以一致自然是最理想的效果。
压测过程:
使用Jmeter发送测试数据来模拟用户请求,性能测试的配置文件主要由数据文件配置(线程间共享方式、到达末尾时的行为等)、吞吐量控制、HTTP采样器(域名、端口、HTTP METHOD、请求body等)、响应断言(对返回结果的内容进行校验)。
在linux中,sar、top、ps等命令都可以对cpu使用情况进行监控。常用的是top命令。
在性能测试中,可以使用如下参数让top命令按需运行:
top –n 1 –b –p ${pid}
# top -n 1 -b -p 103
top - 03:50:39 up 2 days, 21:09, 0 users, load average: 0.01, 0.00, 0.00
Tasks: 1 total, 0 running, 1 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.1 us, 0.0 sy, 0.0 ni, 99.4 id, 0.4 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem: 1020668 total, 911792 used, 108876 free, 44280 buffers
KiB Swap: 425980 total, 273768 used, 152212 free. 134372 cached Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
103 root 20 0 20252 2704 2220 S 0.0 0.3 0:00.03 bash
服务器负载
linux中,服务器负载使用uptime命令获取,该命令的输出如下图
# uptime
03:49:20 up 2 days, 21:07, 0 users, load average: 0.03, 0.01, 0.00
#每一列的含义如下:
#“当前时间 系统运行时长 登录的用户数最 近1分钟、5分钟、15分钟的平均负载”
内存
准确的内存信息在/proc/${PID}/status中,
# cat /proc/103/status
Name: bash
Umask: 0022
State: S (sleeping)
Tgid: 103
Ngid: 0
Pid: 103
PPid: 0
TracerPid: 0
Uid: 0 0 0 0
Gid: 0 0 0 0
FDSize: 256
Groups:
NStgid: 103
NSpid: 103
NSpgid: 103
NSsid: 103
VmPeak: 20316 kB
VmSize: 20252 kB
VmLck: 0 kB
VmPin: 0 kB
VmHWM: 3328 kB
VmRSS: 2704 kB
RssAnon: 484 kB
RssFile: 2220 kB
RssShmem: 0 kB
VmData: 408 kB
VmStk: 132 kB
VmExe: 968 kB
VmLib: 2312 kB
VmPTE: 56 kB
VmPMD: 12 kB
VmSwap: 0 kB
HugetlbPages: 0 kB
Threads: 1
SigQ: 0/3950
SigPnd: 0000000000000000
ShdPnd: 0000000000000000
SigBlk: 0000000000010000
SigIgn: 0000000000380004
SigCgt: 000000004b817efb
CapInh: 00000000a80425fb
CapPrm: 00000000a80425fb
CapEff: 00000000a80425fb
CapBnd: 00000000a80425fb
CapAmb: 0000000000000000
NoNewPrivs: 0
Seccomp: 2
Cpus_allowed: 1
Cpus_allowed_list: 0
Mems_allowed: 00000000,00000001
Mems_allowed_list: 0
voluntary_ctxt_switches: 455
nonvoluntary_ctxt_switches: 419
#上面命令的输出中,关注VmRSS、VmData、VmSize
磁盘IO
*使用vmstat、iostat 前需要现安装sysstat,请使用各版本linux 安装包管理工具安装比如,yum,zypper,pacman,apt-get 等 *
- 使用vmstat获取内核线程、虚拟内存、磁盘、陷阱和 CPU 活动的统计信息
# vmstat
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
0 1 271424 92604 51196 193000 1 2 5 16 63 24 0 0 99 0 0
#Free – 空闲的内存空间
#si – 每秒从磁盘中交换进内存的数据量(以KB为单位)。
#so – 每秒从内存中交换出磁盘的数据量(以KB为单位)。
##带时间戳,每隔2秒执行一次,执行6次后结束
vmstat -t 2 6
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- -----timestamp-----
r b swpd free buff cache si so bi bo in cs us sy id wa st UTC
1 0 271424 92604 51232 193008 1 2 5 16 63 24 0 0 99 0 0 2017-09-24 06:20:51
0 0 271424 92604 51232 193008 0 0 0 0 60 191 0 0 100 0 0 2017-09-24 06:20:53
0 0 271404 92480 51232 193008 16 0 16 0 65 197 0 0 97 3 0 2017-09-24 06:20:55
0 0 271404 92480 51232 193008 0 0 0 0 63 181 0 0 100 0 0 2017-09-24 06:20:57
0 0 271404 92480 51232 193008 0 0 0 0 65 192 0 0 100 0 0 2017-09-24 06:20:59
0 0 271404 92480 51232 193008 0 0 0 0 62 186 0 0 100 0 0 2017-09-24 06:21:01
##输出各种事件计数器和内存的统计信息
# vmstat -s
1020668 K total memory
683832 K used memory
495484 K active memory
354372 K inactive memory
92604 K free memory
51224 K buffer memory
193008 K swap cache
425980 K total swap
271424 K used swap
154556 K free swap
36452 non-nice user cpu ticks
71 nice user cpu ticks
8353 system cpu ticks
25502475 idle cpu ticks
104763 IO-wait cpu ticks
0 IRQ cpu ticks
760 softirq cpu ticks
0 stolen cpu ticks
1372817 pages paged in
4017580 pages paged out
43118 pages swapped in
115463 pages swapped out
16161596 interrupts
49031514 CPU context switches
1505976095 boot time
5028 forks
##更多命令可以参照:https://www.thomas-krenn.com/en/wiki/Linux_Performance_Measurements_using_vmstat
- iostat命令获取CPU统计信息,设备和分区的输入/输出统计信息。
iiostat -x
Linux 4.12.4-1-ARCH (Arch) 09/24/2017 _x86_64_ (1 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
0.14 0.00 0.04 0.41 0.00 99.42
Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
sda 0.13 0.73 0.23 0.37 5.31 15.55 70.05 0.01 17.78 10.61 22.14 7.38 0.44
##只输出cpu统计信息
iostat -c
Linux 4.12.4-1-ARCH (Arch) 09/24/2017 _x86_64_ (1 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
0.14 0.00 0.04 0.41 0.00 99.41
##只输出磁盘的输入输出统计信息
iostat -d
Linux 4.12.4-1-ARCH (Arch) 09/24/2017 _x86_64_ (1 CPU)
Device: tps kB_read/s kB_wrtn/s kB_read kB_wrtn
sda 0.60 5.33 15.61 1373061 4018260
##更多参数和方法可以参考:https://linux.die.net/man/1/iostat
网络
请使用各版本linux 安装包管理工具安装比如,yum install,zypper install,pacman -S,apt-get nethogs 安装 。
NetHogs是一个小型的’net top’工具,不像大多数工具那样拖慢每个协议或者是每个子网的速度而是按照进程进行带宽分组.NetHogs NetHogs不需要依赖载入某个特殊的内核模块. 如果发生了网络阻塞你可以启动NetHogs立即看到哪个PID造成的这种状况.这样就很容易找出哪个程序跑飞了然后突然占用你的带宽.
##只用来监视设备(enp0s8)的网络带宽可以使用如下命令:
# nethogs enp0s8
Ethernet link detected
Waiting for first packet to arrive (see sourceforge.net bug 1019381)
NetHogs version 0.8.5
PID USER PROGRAM DEV SENT RECEIVED
767 arch sshd: arch@pts/0 enp0s8 0.131 0.064 KB/sec
? root unknown TCP 0.000 0.000 KB/sec
TOTAL
##用’-d’来添加刷新频率参数,`device name` 用来检测给定的某个或者某些设备的带宽(默认是eth0).例如:设置5秒钟的刷新频率,键入如下命令即可:
# nethogs enp0s8 -d 5
Ethernet link detected
Waiting for first packet to arrive (see sourceforge.net bug 1019381)
NetHogs version 0.8.5
PID USER PROGRAM DEV SENT RECEIVED
? root 192.168.56.202:8090-192.168.56.1:64341 0.077 0.070 KB/sec
767 arch sshd: arch@pts/0 enp0s8 0.000 0.000 KB/sec
? root unknown TCP 0.000 0.000 KB/sec
TOTAL 0.077 0.070 KB/sec
##工具使用参考链接:https://github.com/raboof/nethogs
测试报告输出
统计完性能测试过程中收集的监控指标后,生成可视化报表。
- 通常来说,性能报告中要包含如下内容:
测试结论:包括被测服务最大QPS、响应时间等指标是否达到期望,部署建议等。
测试环境描述:包括性能需求、测试用服务器配置、测试数据来源、测试方法等
监控指标统计:响应时间统计、QPS、服务器指标统计,进程指标统计。
结语
性能测试需要提升的地方:
- 结合系统历史性能数据进行动态趋势分析和判断
- 综合测试因素,数据给出测试结论
- 提出性能测试改进项,性能测试平台建设
整理自论坛和个人工作经验,此处是基础,希望大家给予建议和指正。