性能瓶颈分析思路
性能瓶颈分析思路
性能分析是一个大课题,不同的架构、不同的应用场景、不同的程序语言分析的方法各有差异,抽象一下大致分为二类:
自底向上:通过监控硬件及操作系统性能指标(CPU、内存、磁盘、网络等硬件资源的性能指标)来分析性能问题(配置、程序等的问题)。因为用户请求最终是由计算机硬件设备来完成的,做事的是 CPU。
自顶向下:通过生成负载来观察被测试的系统性能,比如响应时间、吞吐量;然后从请求起点由外及里一层一层的分析,从而找到性能问题所在。
不管是自底向上还是自顶向下,关键点就是生成负载、监控性能指标。上面我们说了两种方法,大家会问哪一种方法更好呢?哪种方法更简单一点呢?我想说的是方法无所谓好坏,只是一个思路。
对于没有经验的性能测试工作者,提倡自底向上;对于经验丰富的性能测试工作者,先用自顶向下的方式解决掉明显性能问题,再接合自底向上的方式分析更深层次的问题。
性能分析流程
从性能测试工程师的角度来讲解一下通常的性能分析过程(操作系统以Linux为例)。
序号 |
步骤名称 |
说明 |
1.0 |
检查RT |
模拟用户发起负载后,采用自顶向下的方式首先分析RT(响应时间)。 1.如果RT小,TPS大,说明性能良好。 2.如果RT小,TPS小,检查负载机资源占用情况,确定是否要加大负载。 3.如果RT大,TPS小,检查负载机的资源消耗,确保不是负载机的性能原因导致的RT变大。 |
1.1 |
检查TPS |
1.TPS大时RT小,说明性能良好 2.TPS小时RT大,检查负载机的资源消耗,确保不是负载机的性能原因导致的RT变大。 |
2.0 |
检查负载机资源消耗耗 |
1.检查CPU使用率,CPU负载(LoadAverage)确认是用户CPU占用高还是系统CPU占用高?确认测试脚本没有性能问题,不会造成结 果统计的不准确 2.检查内存使用情况,确认并发内存泄露风险,不会造成结果统计的不准确。 3.检查网络占用带宽。大家可以做个小实验,一台并发100用户,一台运行一个用户,比较两者的响应时间是否在同一个数量级,从而评估负载机对性能的影响。 |
2.1 |
判下负载机是否有性能问题 |
排除负载机的性能问题,确保测试结果可参考。 |
3.0 |
检查Web 服务器的资源消耗 |
1.检查CPU使用率,确认用户CPU与系统CPU占用情况 1.1系统CPU占用多,检查系统调用情况,找出是哪个进程或线程,确认调用是否正常?比如滥写日志,导致系统CPU利用率高。 1.2用户CPU高,找出进程或线程,定位到程序,确认是否调用正常?一般来说Web服务程序不涉及到运算的,CPU利用率高要确认是否是其它资源等待导致的CPU利用率高。 1.2.1比如IO等待会带来CPU利用率高,CPU由于等待IO,而频繁的进行上下文切换。 1.2.2比如事务过程较长,需要锁定的资源较多,而请求也较多时,CPU需要不停的中断、上下文切换去处理获取到资源的请求。 2.检查内存使用情况,找出占内存多的进程或线程 3.检查磁盘使用情况,找出IO量大的进程或线程 4.检查占用的带宽 5.分析Web页面响应的时间组成 |
3.1 |
确认是否 Web服务器瓶颈 |
从3.0监控指标判断是否是Web服务器硬件性能瓶颈。 |
3.2 |
检查中间 件配置 |
1.检查中间件线程池活动连接数,确认是否是此配置问题。 2.检查Heap配置,确认gc的影响。 |
3.3 |
是否是中间件限制 |
1.监控线程池活动连接数,确认线程池够用。 2.监控线程状态,如果长期是Blocked状态,可能是响应慢,有可能会导致死锁,Dump线程栈找到疑问程序。 3.监控JVM,关注GC,评估Heap空间是否够用。 |
4.0 |
检查APP 服务器资源消耗 |
分析方法同3.0。 |
4.1 |
确认是否 App服务器瓶颈 |
从3.0监控指标判断是否是App服务器硬件性能瓶颈 |
4.2 |
检查中间 件配置 |
1.检查中间件线程池。 2.检查数据库连接池。 3.检查Heap配置。 |
4.3 |
是否是中间件限制 |
1.监控线程池,确认线程池够用。 2.监控线程状态,如果长期是Blocked状态,代表响应慢,有可能会导致死锁。 3.监控与数据库的连接数,确认数据库连接池是否够用。 4.监控JVM,关注GC,评估Heap空间是否够用。可以借助JVisualVM、 Jprofiler来分析,也可以使用Jdk自带的监控命令。 |
5.0 |
数据库服务器资源消耗分析 |
1.CPU消耗,CPU负载。 2.内存消耗。 3.IO繁忙程度。 4.数据库监控 4.1慢查询。 4.2对DB不熟悉的读者可以找DBA帮忙监控分析。 |
5.1 |
是否是DB 性能问题 |
由5.0的监控结果来判断是否是DB性能问题。 |
linux主机瓶颈阀值分析
CPU定位分析
模块 |
类型 |
度量方法 |
衡量标准 |
CPU |
使 用 情况 |
|
注意>=50% 告警>=70% 严重>=90% |
CPU |
满载 |
|
运行的队列大于cpu逻辑颗数时,证明已经有一定的负载了,不过这个计数也不绝对,需进一步分析其他的资源情况来断定是否 CPU已经满负荷运作 |
我们可以用的命令有vmstat, top ,sar,dstat, mpstat, ps 等命令来进行统计分析。
vmstat 字段含义说明:
类别 |
项目 |
含义 |
说明 |
Procs(进程) |
r |
等待执行的任务数 |
展示了正在执行和等待cpu资源的任务个数。当这个值超过了cpu个数,就会出现cpu瓶颈。 |
B |
等待IO的进程数量 |
|
|
Memory(内存) |
swpd |
正在使用虚拟的内存大小,单位k |
|
free |
空闲内存大小 |
|
|
buff |
已用的buff大小,对块设备的读写进行缓冲 |
|
|
cache |
已用的cache大小,文件系统的cache |
|
|
Swap |
si |
每秒从交换区写入内存的大小(单位:kb/s) |
|
so |
每秒从内存写到交换区的大小 |
|
|
IO |
bi |
每秒读取的块数(读磁盘) |
现在的Linux版本块的大小为1024bytes |
bo |
每秒写入的块数(写磁盘) |
|
|
system |
in |
每秒中断数,包括时钟中断 |
这两个值越大,会看到由内核消耗的cpu时间会越多 |
cs |
每秒上下文切换数 |
||
CPU(以百分比表示) |
Us |
用户进程执行消耗cpu时间(user time) |
us的值比较高时,说明用户进程消耗的cpu时间多,但是如果长期超过50%的使用,那么我们就该考虑优化程序算法或其他措施了 |
Sy |
系统进程消耗cpu时间(system time) |
sys的值过高时,说明系统内核消耗的cpu资源多,这个不是良性的表现,我们应该检查原因。 |
|
Id |
空闲时间(包括IO等待时间) |
|
|
wa |
等待IO时间 |
Wa过高时,说明io等待比较严重,这可能是由于磁盘大量随机访问造成的,也有可能是磁盘的带宽出现瓶颈。 |
内存定位分析
模块 |
类型 |
度量方法 |
衡量标准 |
内存 |
使用情况 |
|
注意>=50% 告警>=70% 严重>=80% |
内存 |
满载 |
|
OOM机制 |
我们可以用的命令有 vmstat,sar,dstat, free, top , ps 等命令来进行统计分析。
free 字段含义说明:
参数
|
释义
|
---|---|
total | 内存总数,物理内存总数 |
used | 已经使用的内存数 |
free | 空闲的内存数 |
shared | 多个进程共享的内存总额 |
buffers/cache | 缓存内存数 |
available | 可用内存数 |
Swap | 交换分区,虚拟内存 |
网络定位分析
模块 |
类型 |
度量方法 |
衡量标准 |
网络 |
使用情况 |
|
|
网络 |
满载 |
|
统计的丢包有计数证明已经满了 |
网络 |
错误 |
|
错误有计数 |
衡量系统网络的使用情况,我们可以使用的命令有ifstat,iftop,netstat以及查看net的速率,通过查看发现收发包的吞吐速率达到网卡的最大上限,网络数据报文有因为这类原因而引发的丢包
阻塞等都证明当前网络可能存在瓶颈。在进行性能测试时为了减小网络的影响,一般我们都是在局域网中进行测试执行。
nicstat命令详解
磁盘IO定位分析
模块 |
类型 |
度量方法 |
衡量标准 |
IO |
使用情况 |
|
注意>=40% 告警>=60% 严重>=80% |
IO |
满载 |
|
IO 已经有满载嫌疑 |
IO |
错误 |
|
有信息 |
衡量系统IO的使用情况,我们可以使用的命令有sar, iostat,iotop等命令进行系统级的IO监控分析。当发现IO的利用率大于40%时候,就需要注意了,当使用率大于60%则处于告警阶段,大于80%IO就会出现阻塞了。
iostat -x命令详解
选项
|
说明
|
---|---|
rrqm/s | 每秒对该设备的读请求被合并次数,文件系统会对读取同块(block)的请求进行合并 |
wrqm/s | 每秒对该设备的写请求被合并次数 |
r/s | 每秒完成的读次数 |
w/s | 每秒完成的写次数 |
rkB/s | 每秒读数据量(kB为单位) |
wkB/s | 每秒写数据量(kB为单位) |
avgrq-sz | 平均每次IO操作的数据量(扇区数为单位) |
avgqu-sz | 平均等待处理的IO请求队列长度 |
await | 平均每次IO请求等待时间(包括等待时间和处理时间,毫秒为单位) |
svctm | 平均每次IO请求的处理时间(毫秒为单位) |
%util | 采用周期内用于IO操作的时间比率,即IO队列非空的时间比率 |
tomcat 性能监控和分析
连接器(Connector)的参数配置
- HTTP/1.1:默认值,使用的协议与Tomcat版本有关
- org.apache.coyote.http11.Http11Protocol:BIO
- org.apache.coyote.http11.Http11NioProtocol:NIO
- org.apache.coyote.http11.Http11Nio2Protocol:NIO2
- org.apache.coyote.http11.Http11AprProtocol:APR
Attribute
|
描述
|
---|---|
maxConnections |
服务器在任何给定时间接受和处理的最大连接数。当达到这个数字时,服务器将接受一个进一步的连接,但不会处理。这个附加连接将被阻塞,直到正在处理的连接数降到maxConnections以下,服务器再次开始接受并重新处理新的连接。 |
acceptCount | 所有可能的请求处理线程正在使用时,传入连接请求的最大队列长度。 当队列满时收到的任何请求都将被拒绝。 默认值为100。 |
connectionTimeout | 连接器在接受连接后等待的请求URI行的毫秒数。 使用值-1表示无(即无穷大)超时。 默认值为60000(即60秒),但请注意Tomcat附带的标准server.xml将其设置为20000(即20秒)。 除非disableUploadTimeout设置为false,否则读取请求主体(如果有的话)也将使用此超时。 |
keepAliveTimeout | 连接器在关闭连接之前等待另一个HTTP请求的毫秒数。 默认值是使用为connectionTimeout属性设置的值。 使用值-1表示无(即无穷大)超时。 |
maxKeepAliveRequests | 在服务器关闭连接之前可以进行流水线处理的最大HTTP请求数。将此属性设置为1将禁用HTTP / 1.0保持活动状态,以及HTTP / 1.1保持活动状态和流水线状态。将其设置为-1将允许无限量的流水线或保持活动的HTTP请求。如果未指定,则此属性设置为100。 |
executor | 对Executor元素中的名称的引用。 如果设置了此属性,并且命名的执行程序存在,则连接器将使用执行程序,并且所有其他线程属性将被忽略。 请注意,如果未为连接器指定共享执行程序,则连接器将使用专用的内部执行程序来提供线程池。 |
线程池Executor的参数配置
- name:该线程池的标记
- maxThreads:线程池中最大活跃线程数,默认值200(Tomcat7和8都是)
- minSpareThreads:线程池中保持的最小线程数,最小值是25
- maxIdleTime:线程空闲的最大时间,当空闲超过该值时关闭线程(除非线程数小于minSpareThreads),单位是ms,默认值60000(1分钟)
- daemon:是否后台线程,默认值true
- threadPriority:线程优先级,默认值5
- namePrefix:线程名字的前缀,线程池中线程名字为:namePrefix+线程编号
tomcat监控
对tomcat的监控主要就是查看服务器中的连接数和线程数,以及线程状态的监控
查看大致分为两种方案:(1)使用现成的工具,(2)直接使用Linux的命令查看。
命令方式:
查看线程数
ps -Lf 163610 |wc -l
查看连接数
netstat -nat|awk '{print $6}'|sort|uniq -c|sort
工具监控:tomcat manager,JProfiler,JConsole,jvisualvm, Btrace等
下图是tomcat manager监控页面
线程问题
1、Deadlock问题必须要解决,
2、大量线程处于Blocked状态 waiting状态
3、线程不够用
4、线程占用资源高需要分析
命令行分析资源消耗最高的线程
实例讲解
下面已本次支付性能测试的一个性能问题为实例来讲解整个分析过程
1、通过查看tps和响应时间,确认存在性能瓶颈
2,检查日志,发现有错误日志,首先解决错误日志问题,但是性能问题依旧未解决
3、监控服务进程资源,发现cpu利用率为200%多,内存, IO都无瓶颈
4、监控可以看出时间都消耗在tss服务内部,考虑通过线程分析是否有阻塞导致,通过命令jstack打印线程堆栈信息
jstack -l PID >tmp.txt