监控并分析Windows和Linux关键性能指标
对于性能测试来说,如果没有足够的监控数据,我们则无从对其进行分析,也不能很好地定位性能瓶颈。所以,本节实验将主要为大家讲解如何利用Windows和Linux操作系统下的一些工具,完成对关键性能指标的监控。
实验简介
“巧妇难为无米之炊”,对于性能测试来说,如果没有足够的监控数据,我们则无从对其进行分析,也不能很好地定位性能瓶颈。所以,本节实验将主要为大家讲解如何利用Windows和Linux操作系统下的一些工具,完成对关键性能指标的监控。
实验目的
(1) 深刻理解操作系统常用的关键性能指标的作用。
(2) 能够自主设计实验完成对性能指标的监控与确认。
(3) 熟练使用Windows自带的性能监控工具实施指标监控。
(4) 熟练使用Linux自带的性能监控工具实施指标监控。
(5) 熟练使用NMon监控工具完成对Linux环境下的性能指标监控。
实验流程
1. 操作系统的关键性能指标
操作系统作为应用系统运行的载体,其作用不言而喻。所以对于一个应用系统的性能消耗情况,通过监控操作系统底层的性能指标,基本上可以对系统的性能情况有一个全面的掌握。通常情况下,对于一个软件系统的运行来说,我们通常监控下面一系统操作系统级指标:
(1) CPU使用率(%Processer Time):决定了系统在高负载情况下消耗CPU的情况。CPU是一台服务器的心脏,也为多线程运行提供了底层支持。而服务器在处理高并发请求时,也都是依靠线程来完成,所以线程的使用对CPU的消耗是显而易见的。另外一个方面,任何一个系统都会存在大量的运算,都需要利用CPU提供运算支持。所以基本上很多系统的CPU都容易成为性能瓶颈。
(2) CPU队列长度(%Processer Time):当CPU忙不过来的时候,就会产生很多排队等待CPU资源的处理任务。队列越长说明CPU越忙。
(3) 可用内存数(Available Mbytes):可用的内存大小,单位为兆字节。这是一个相对简单的指标,可用内存数越大,说明内存不是问题。基本上来说目前内存都不太可能成为瓶颈。因为我们增加内存的成本相对较低。
(4) 页交换频率(Page/sec):内存与虚拟内存(硬盘)之间进行数据交换(俗称页交换)的频率,越低越好。这是一个历史遗留问题,在早期的计算机系统中,内存容量都很小,经常出现内存不够用的情况。但是一个系统的程序都是运行于内存中的,如果内存不够则无法运行。所以系统设计人员想到了一个办法,利用硬盘来伪装成内存。当内存实在不够用的时候,就从硬盘中切出一块空间来专门用于虚拟内存,将一些暂时不使用但是又不能清除的内存数据交换到这块虚拟内存的硬盘空间里临时保存起来。这样,就会存在物理内存与虚拟内存进行数据交换的过程。但是由于硬盘的读写速度实在太慢(相比内存来说,基本上慢至少100倍左右,此处指传统的机械硬盘,固态硬盘会比机械硬盘快5倍左右,当然,不同的设备和接口规格,速度差异也不小),所以我们应该尽量减少虚拟内存的使用,进而减少页交换的频率,提升程序的运行效率。只要可用内存数量够,建议可以调高缓存来降低其值。
在Windows的系统安装盘(比如C:盘)下存在一个系统级隐藏文件叫:“pagefile.sys”,或者在Linux当中的特殊分区“/swap”,都是硬盘专门切分出来的一块用于虚拟内存的专属空间。但是为什么是“页交换”呢,因为在内存中,管理一块内存空间的单位称为“页”,由此得名。
(5) 设置虚拟内存大小:通常情况下,操作系统为默认帮我们分配虚拟内存的大小,通常是物理内存的1.5到2倍,但是这是可以修改的。在Linux中,我们只需要简单的调整“/swap”分区的大小即可。在Windows中,我们可以打开“我的电脑”->“属性”->“高级系统设置”打开系统设置对话框,在“高级”选项卡的性能“设置”中打开“性能选项”,在“高级”选项卡中打开虚拟内存的“更改设置”,并调整为手工设置即可。设置完成后重启电脑,便可以生效,这个设置大小就是“pagefile.sys”的文件大小。如下图所示:
(6) 磁盘使用率(% Disk Time):类似于CPU使用率,硬盘处于读写等工作状态所占的比例。该值越大,表示硬盘越忙,说明硬盘有可能会成为瓶颈。比如Web服务器会大量读取一些静态资源文件,如图片,JS文件或CSS文件等,或者在数据库中频繁操作硬盘上的数据文件等,都会容易导致硬盘使用率飙高,引起一些性能问题。对于硬盘的性能瓶颈,标准的解决方案就是有效利用缓存,来缓解硬盘的读写压力。
(7) 磁盘队列长度(Avg.Disk Queue Length):类似于CPU队列长度,当磁盘忙不过来的时候,则会有读写队列产生,一般只要是在个位数,瞬间的队列是正常的。
(8) 网络带宽消耗:任何客户端的请求和服务器端的响应,都需要经过网络进行传输,所以网络带宽是非常容易出现瓶颈的。我们在进行性能测试时,对网络带宽的监控通常关注网卡每秒钟接收到的数据(Bytes Received/sec)和每秒钟传输出去的数据(Bytes Sent/sec),如果该数据与网络带宽相当,则说明带宽已经是瓶颈了。目前对于带宽要求最高的,主要是视频类网站,图片类网站(一些电商网站中的图片也非常多)或者资源下载站点等。这类系统的性能瓶颈基本上都是由带宽导致的,而在互联网上,带宽的租用是非常昂贵的。也正因为这样,我们才会一直致力于研究更优的算法来对图片,文件或者视频进行压缩。比如图片压缩算法JPEG-2000,文件压缩算法GZip,或者视频压缩算法H.265等。但是这里仍然存在一个问题,越高效的压缩算法,意味着越消耗CPU资源,无论是压缩还是解压缩过程均是这样的。这是一个无法兼得的情况,我们必须寻找平衡。
2. 关于缓存的进一步解释
我们在性能测试部分大量提到了“缓存”这个东西,那么到底缓存指哪些层面,如何有效地利用好“缓存”,目前常见的一些缓存应用有哪些呢?
(1) 什么是缓存?缓存其实是一个很泛的概念,并不特指内存。比如在浏览器的临时文件目录中保存的网页静态资源,也可以称之为浏览器缓存,但是这些资源却是保存在硬盘上的。所以,我们应该换一个角度来理解缓存:充分利用更快的存储设备,以缓解更慢的存储设备的处理压力,并且尽量不要因为慢速设备而拖了整个系统的后腿。
(2) 常见的一此存储设备的速度:通常情况下一根标准DDR3内存条的读写速度大约在10GB/s左右(当然,不同厂商的不同规格的内存条会有差异)。而一块机械硬盘的读写速度,平均可能就只有不到100MB/s,如果是随机读取一些小文件,速度会更慢。固态硬盘虽然比机械硬盘快(目前最新固态硬盘的实际读写速度平均来说500MB/s是个极限了已经),所以,很多时候,系统慢,硬盘和CPU通常是很重要的原因,内存反而不太容易成为瓶颈。另外一方面,机械设备的老化,导致数据传输效率受损也是原因之一。其实,在计算机系统中,存在各种各样的缓存,内存其实并不是最快的存储设置。最快的存储设置是集成在CPU当中的一级缓存,二级缓存和三级缓存。笔者利用AIDA64(早期名叫Everest)这个工具对自己的电脑进行了一下内存和CPU缓存的测试,其速度如下:
我们可以看到,笔者电脑的内存读写速度平均算下来差不多有19GB/s,而当前i5的CPU一级缓存的读取速度更是丧心病狂地达到了192GB/s,当然,一级缓存的造价是非常昂贵的,笔者的这台CPU的一级缓存只有“128KB”,已经算是较大的了。事实上,我们可以这样理解,针对一台电脑的四个核心组成部分:“CPU,内存,硬盘,网络”来说,硬盘是网络的缓存,内存是硬盘的缓存,CPU缓存是内存的缓存。而通常,一个系统运行的I/O路径也遵循上述顺序。所以,对于CPU来说,内存的处理速度还是太慢了,所以直接集成一二三级缓存,来缓解CPU与内存处理速度上的差异。
下图是笔者电脑上的一块相对较老的固态硬盘,在针对8M大文件进行线性读取(这是硬盘读取文件时速度最快的组合)时的速度,平均速度只有193MB/s,笔者另外一台使用PCI-e接口的固态硬盘的电脑,其速度也就是450MB/s左右,也已经算是很快的固态硬盘了。而针对4K小文件进行随机读取(这是硬盘读取文件时速度最慢的组合),只有大约40MB/s,比起机械硬盘来说,固态硬盘的强项就是小文件的处理,这已经是比较理想的状态了。
(3) Web服务器缓存:通常情况下,对于Web服务器来说,使用硬盘最多的情况就是读取服务器端的静态资源文件,如图片,CSS文件,JS脚本等。这些静态资源都是保存在硬盘中的,每一次情况都会读取这些资源。所以如果我们设置更大的缓存,将这些静态资源直接缓存在服务器的内存中,则可以减少对硬盘的读写。比如在Apache中,我们可以启用“mod_cache”这个模块来有效地使用缓存。
(4) 数据库服务器缓存:对于数据库服务器来说,则更加依赖硬盘的性能。由于现在的关系型数据库均是将数据文件保存在硬盘中,每一次执行SQL时,都可能会读写硬盘数据。所以,对于一台数据库服务器来说,硬盘的性能一定要好。也正因为如此,数据库服务器也同样为我们提供了缓存策略,可以让我们把一些已经查询过的数据保存到内存中,供下次查询时直接使用。但是,通常对于数据库更新时,为了保存数据的同步,通常并不建议通过缓存来更新,而是直接更新到数据文件中。这就必然会牵涉到大量的写硬盘操作。所以,在数据库性能指标中有一个很特别的指标叫“SQL命中率”,这个指标越高,说明缓存起的作用越大。
(5) 缓存服务器:除了数据库自身的一些性能参数的设置外,目前在数据库领域,比较流行的缓存服务器是Redis,这是一种键值对的缓存服务器。可以灵活地设置缓存策略,也支持将已经查询过的数据保存在缓存中,如果下次查询到相同的数据,则直接命中,不需要再经过数据库服务器来进行处理,直接把结果从Redis中返回给请求端。
(6) 内存型数据库:其实Redis本身就可以认为是一个内存型数据库,除此之外,目前市面上比较流行的内存型数据库有Timesten,AltiBase,Extreme,CacheDB等。其基本特点就是将数据库直接加载到内存当中来运行。但是目前这些数据库还没有办法进行全面应用最主要的原因有两点:一是应用系统的迁移成本巨大,二是其数据的高可用性考虑。因为内存一旦断电,数据荡然无存。虽然各内存型数据库厂商都提供了很不错的解决方案,一些传统的观念仍然在影响着企业的决定。最后的结局就是,小系统不需要用,因为数据库没有什么瓶颈,大系统不敢用,因为数据重于一切。
(7) 线程池和连接池:线程池和连接池是网络服务器中必备的两种提升性能的方法。线程池的使用,主要用于减少线程不停地创建又销毁这些无效操作,让线程可以重复使用而不会被销毁。就像连接池的使用一样,尽量避免网络连接的频繁创建又断开,把有限的资源使用到处理业务上,而不是建立连接,创建线程这些事情上。那是不是线程池或连接池越多越好呢,当然,如果CPU资源够的话,理论上来说是这样的。但是事情都有两面性,特别是对于多层服务器架构来说,我们必须要考虑到每一层服务器在处理能力上的协调。瓶颈永远不会产生在高配置的电脑上,整个系统中最弱的环境才会导致瓶颈。举个简单的例子,CPU即使很强悍,能够同时处理的请求非常多,但是网络带宽能不能处理这么大的吞吐量呢?
如果不行,那么CPU再强悍也是枉然。
3. 关于硬盘的性能
硬盘分为固态硬盘和机械硬盘,通常影响硬盘的处理主要由三个方面构成:
(1) 硬盘的内置缓存。通常情况下,固态硬盘的高速缓存可以达到256MB甚至更多,而机械硬盘的高级缓存通常只有32MB或者最多64MB,所以固态硬盘快于机械硬盘,调整缓存也是一个影响因素。当然,更高的高速缓存意味着更贵的价格。
(2) 硬盘的转速。比如民用的SATA硬盘,转速最多就7200转/分钟,而服务器专用的SAS硬盘,转速至少都是10000转/分钟。
(3) 扇区大小。扇区是磁盘保存数据的最小单位,在Windows中,默认扇区大小为4KB,而在Linux操作系统中,默认扇区大小为8KB,扇区的大小在格式化磁盘的时候指定。扇区的大小意味着存储数据的最小单位。比如我们设置扇区大小为4K,那么即使一个1字节的文件,也会最小消耗4K存储空间。下图是笔者的一个只有533个字节的文本文件,同样占用了4K的大小。
扇区设置得越小,越节省磁盘空间,因为每一个扇区的利用率更高。但是性能也会随之下降,因为如果我们要在磁盘上保存一个100M的文件,对于一个4K扇区大小的磁盘分区来说,就需要25600个扇区来保存。那么,硬盘在读取这个文件时,需要向25600个扇区去取内容。而如果我们将扇区调整为64K大小,那么只需要向1600个扇区取内容,虽然会显著降低硬盘的读取速度。但是,这样的话,一个再小的文件,我们也必须浪费64K空间来存储。因为一个扇区只对应一个编号,里面不能存储两个文件的内容,这样硬盘是没办法正确读取到里面的内容的。
(4) 磁盘碎片:当硬盘使用较久的时候,我们应该进行硬盘的碎片整理,否则硬盘的读取速度会变慢。这是很多人都知道的常识,但是其原因是什么呢?通常情况下,硬盘当中的文件如果按照扇区顺序保存,机构硬盘的磁头就可以减少寻址的消耗,按顺序挨个把内容读取出来即可。但是,当硬盘使用太久后,由于文件的添加,删除等操作,导致硬盘需要将一些文件分别保存到一些不连续的扇区中。那么在读取文件内容时,磁头就需要一会儿跑到这个扇区来取一次数据,然后马上就转N圈,跑到另外一个扇区去取内容,无疑会增加磁头的寻址时间,降低性能。磁盘碎片整理的原理就在于把分散在各不连续扇区的文件内容移动到挨着的扇区,减少磁头的寻址时间。
另外,对于很多严谨的服务器环境,我们还提供磁盘阵列(RAID),NAS(Network Attached Storage,即网络附属存储)等手段来提升硬盘的可靠性和性能。比如我们可以利用RAID 0把一个数据分块往N块不同的硬盘上写,这样性能便可以提升N倍,当然这样做的风险就是一旦某块硬盘损坏,数据无法修复。所以,基于处理速度和可靠性的考虑,还提供了RADI0,1,2,3,4,5,6,7,10,53等各种规范。当然,这些都意味着成本,其实任何性能问题,如果通过花钱就能解决的问题,那么将不再是问题。无论是CPU,内存,硬盘还是带宽,都是这个道理。我们做性能测试和性能优化的目的,就是在不增加更多成本的基础上,尽最大可能压榨系统的性能。
4. 监控Windows性能指标
Windows操作系统提供了“任务管理器”,可以非常方便地监控到常见的几个性能指标,如CPU利用率,内存使用情况,网络使用情况,硬盘IO情况,线程数量等。比如在Windows 2003的任务管理器中,我们可以通过在“查看”菜单下的“选择列”这个操作中把一些要监控的指标纳入到监控中:
在新版本的Windows中,还提供了更细致的监控,比如笔者的Windows 10操作系统中的“资源监视器”,前面线程的学习中已经讲解过。但是无论是“任务管理器”还是“资源监视器”的监控,都存在一个问题,就是它是实时的显示数据,而无法保存性能数据,当然也无法用于后续的分析,仅仅是用于调试时比较方便而已。但是我们在实施性能测试的过程中,肯定是需要保存这些性能数据的,以供后续的分析。所以此时,我们需要使用Windows自带的更加全面的“性能监控工具”。
具体操作步骤如下:
(1) 运行性能监视器,通常们于Windows的“管理工具”菜单里面。不同的Windows版本界面和操作上有少许差异,但是整体思路是一致的。笔者的Windows 10的性能监视器启动后如下图所示:
(2) 展开“数据收集器集”,选择“用户定义”,在右侧空白区域点击“右键”->“新建”->“数据收集器集”,打开新建对话框,输入一个收集器集的名称,点击“下一步”并选择“System Performance“选项并点击完成,界面如下。
(3) 在左侧新建的收集器集上点击,进入该收集器集的主界面。然后在右键的“Performance Counter”条目上右键点击“属性”,来为该性能计算器设置一些选项。通常的选项设置为:
通常我们建议将日志格式设置为“逗号分隔”文件(即CSV文件),这样可以使用Excel直接打开。如果选择默认的二进制文件,则我们无法直观地查看监控到的数据。同时,监控时间也建议不要设置为1秒,太频繁的监控也会消耗计算机资源,并且意义不大。2~5秒的监控周期足够。
(4) 为收集器集设置持续时间为不限制,这样我们可以根据需要手工停止。
(5) 选中该数据收集器集,并点击工具栏上的绿色“启动”按钮,开始收集数据。默认设置下,收集到的数据将会保存在“C:\PerfLogs”文件夹中。比如此处我们对当前系统监控一段时间,并且运行一下前面实验中的对Phpwind开发的多线程性能测试脚本(20个线程,每5秒钟加5个,每个线程运行10次)。当运行完成后,停止监控即可。
(6) 在“C:\PerfLogs”目录下的对应文件夹中,我们可以看到本次监控到的性能测试数据。包括最原始的CSV数据文件,及系统帮我们生成的数据报告。我们可以打开“report.html”查看到一些基本的性能数据分析结果。
(7) 但是上述监控数据内容非常多,由于我们使用的是系统自带的模板,所以系统会监控很多指标。但是指标太多后其实并不见得是好事,特别是我们对指标还不够熟悉的时候,“少即是多”,我们应该监控前面提到的几个重要指标,因为这些指标我们非常理解其作用,这样才能够进行有价值的分析。在Windows的“性能监控器”中,我们可以不使用系统自带模板,而是选择自定义指标。基本操作如下:
a) 新建一个数据收集器集,命名后选择“手动创建”,点击下一步。
b) 在“创建数据日志”栏勾选“性能计算器”,点击下一步。
c) 在“性能计数器”中添加我们需要监控的几个关键性能指标即可。如下图所示:
d) 完成上述设置后,右键打开该性能计数器(可能的名称为“DataCollector01”)的属性,为该性能计算器设置文件类型为“逗号分隔”文件。
e) 启动性能测试的时候,启动该性能计数器开始监控即可。当性能测试执行完成后,手工结束该计数器。
5. 分析Windows性能指标
我们按照自定义的性能计算器对Phpwind的性能测试过程进行全程监控。并设置并发操作策略为:“30个用户,每10秒钟添加5个用户,每个用户运行20次”。并对最终得到的数据进行分析。当该性能测试执行过程中,现场实时看到的CPU资源利用率如下:
当执行完成后,我们我们利用Excel直接打开该计数器的CSV文件进行,CSV文件的内容如下图所示:
单纯地这样看会显得比较费劲,所以现在我们完全可以利用Excel提供的一些功能辅助我们更好地来分析这些性能指标。
(1) 对每一列统计其平均情况,比如统计CPU的平均使用率,平均队列长度等。
(2) 利用Excel的图表功能绘制拆线图,更直观地查看性能表现。比如我们对CPU使用率这一列绘制拆线图如下:
通过上述拆线图我们明显可以看出CPU随着并发线程数据增加而增加,减少而减少。并且在30个并发线程的时候,CPU已经达到了100%,出现了瓶颈。当然,此时我们可以继续查看CPU的队列长度的监控数据,分析CPU的瓶颈是否严重,如果队列长度比较多,则说明CPU非常忙。如果队列长度整体看起来还好,那么CPU还能基本应付得过来,只是用户会需要多一点等待时间而已。当然,通常一个生产系统中,CPU的使用率一般不应该超过80%。
其它的一些性能指标我们可以利用同样的方式来完成。此处不再赘述。
6. 监控Linux性能指标
就像Windows的任务管理器一样,Linux的所有发行版本中也同样提供了各种监控系统性能指标的命令,比如最典型的“top”命令,此处我们以服务器端常用的“CentOS”操作系统为例为大家讲解。
先来看看Linux中的实时监控命令“top”,类似于Windows中的任务管理器,运行“top”命令后可以监控到的信息如下:
上述命令中的第二行显示了一共有88个任务,1个正在运行,87个正在休眠。第三行显示的则是CPU的信息,有0.2%的CPU资源被用户进程使用(0.2 us),99.7%的CPU资源空闲。第四行显示了物理内存的使用情况,一共有1.8个多G的物理内存,260多M空闲,500多M被使用,1个多G的内存被用于缓存。第五行显示是的交换分区(虚拟内存)的使用情况,目前该使用的交换分区没有被使用。后面的每一行就是每一个进程的具体资源消耗情况。
从上面的数据可以看出,“top”命令监控的数据并不全面。另外一方面,就像Windows一样,我们在进行性能测试的过程中,不可能只关注这个实时信息,我们需要监控一段时间的数据。所以我们更建议大家使用一个由IBM开发的更加专业的性能指标监控工具“NMon”,下载地址为:“http://nmon. sourceforge.net/pmwiki.php”,当我们选择跟自己的Linux系统匹配的版本后直接下载即可,文件比较小,不到1M。下载完成后将该压缩包上传到我们的Linux操作系统中,并按照如下步骤完成操作:
(1) 运行命令“tar –zxvf nmon_xxx.tar.gz”,将压缩包解压到当前文件夹中。
(2) 进入解压后的目录中,利用命令“chmod 755 nmon_xxx”将该执行文件修改为可执行权限。Nmon并没有专门针对CentOS的版本,因为CentOS是与Redhat企业版同源的开源版本,所以我们匹配nmon中的rhel版本即可。
(3) 直接运行命令“./nmon_xxx”即可打开nmon的监控终端,要查看什么信息直接输入对应的指令即可,但是这种用法跟“top”一样,也只能实时查看。
(4) 要将监控数据保存到文件中,我们需要使用另外的命令“./nmon16g_x86_rhel72 -f -s 3 -c 60”即可将监控数据保存到当前目录下,文件名以.nmon为后缀,以机器名和当前时间为文件名命名。上述命令中“-f”参数表示将监控数据输出为一个Excel可以处理的文件,“-s 3”表示每3秒钟监控一次,“-c 60”表示总共采集60次数据。所以整个命令会持续运行3*60=180秒,即3分钟。
(5) 最后,将采集到的nmon数据传输到本地操作系统中即可。
7. 分析Linux性能指标
那么,我们利用nmon监控到的数据该如何使用呢?其实nmon监控到的数据就是一个CSV文件,我们在Linux中可以直接使用命令“sort xxxxx.nmon”查看到该数据,但是这样仍然不太方便。所以nmon还为我们开发了一个专用的Excel插件,可以让我们在Excel更直观地查看数据。
(1) 先搜索“nmon analyser 下载”,找到任意一个可下载链接。
(2) 下载后解压缩,里面有两个文件,一个Word,一个Excel,我们直接打开Excel文件。
(3) 如果Excel弹出安全警告,直接确认启用即可。启用该插件后的主界面如图:
(4) 点击按钮“Analyse nmon data”,在打开的对话框中浏览到在Linux中监控到的nmon数据文件。
(5) 等待加载数据完成后,我们可以看到在Excel中新增了大量新的Sheet,每一个Sheet对应的就是一个关键性能指标,并且自动帮我们生成了分析图表,让我们能够更加直观地进行指标分析。
通常情况下,除了直接监控整个操作系统的上述关键性能指标外。我们还可以基于某个特定的进程进行更详细的监控。这样能够更加容易地获取到当前服务器端对应进程的性能情况,便于我们定位问题。不过通常情况下,这不是主要问题,因为在一个服务器上,通常我们不太会运行过多的其它应用。
思考练习
(1) 请了解关于Apache,IIS,Tomcat,SQLServer, MySQL, Oracle等常用服务器的关键性能指标。
(2) 请自学使用SpotLight性能监控工具。