当前位置: 首页 > 科技观察

6万毫秒内对Linux进行性能诊断

时间:2023-03-18 23:58:19 科技观察

当你在Linux服务器上发现系统性能问题时,你会在第一分钟查看哪些系统指标?Netflix在AWS上拥有大规模的EC2集群,以及种类繁多的性能分析和监控工具。比如我们用Atlas来监控整个平台,用Vector来实时分析EC2实例的性能。这些工具已经能够帮助我们解决大部分问题,但有时我们还是要登录机器,使用一些标准的Linux性能分析工具来定位问题。前60秒在本文中,Netflix性能工程团队将介绍一些我们用来在发现问题的前60秒内分析和定位问题的标准Linux命令行工具。在这60秒中,你可以通过以下10条命令行来了解系统的整体运行情况以及当前运行进程的资源使用情况。在这些指标中,我们首先关注与错误和资源饱和度相关的指标,然后再看资源使用情况。相对来说,错误和资源饱和率比较容易理解。饱和意味着资源(CPU、内存、磁盘)上的负载超过了它可以处理的容量。这时候我们观察到的现象是请求队列开始堆积,或者请求等待时间变长。uptimedmesg|tailvmstat1mpstat-PALL1pidstat1iostat-xz1free-msar-nDEV1sar-nTCP,ETCP1top一些命令行依赖于sysstat包。通过这些命令行的使用,您可以熟悉一套分析系统性能问题常用的方法或流程:USE。该方法主要从资源利用率(Utilization)、资源饱和度(Satuation)、错误(Error)三个方面分析所有资源(CPU、内存、磁盘等)。在这个分析的过程中,要时刻关注我们已经剔除掉的资源问题,从而缩小我们定位的范围,为下一步的定位提供更明确的方向。以下部分提供了每个命令行的解释,并以我们的生产数据为例。关于这些命令行更详细的说明,请参考相应的帮助文档。1.uptime$uptime23:51:26up21:31,1user,loadaverage:30.02,26.43,19.02这个命令可以快速查看系统的平均负载,你可以把这个负载的值看成是有多少任务在等待跑步。在Linux系统上,这包括需要或正在使用CPU的任务,以及在io上被阻塞的任务。这个命令可以让我们对系统的全局状态有一个大概的了解,但是我们仍然需要借助其他工具来获取更多的信息。这三个数值是系统计算出的1分钟、5分钟、15分钟的指数加权动态平均值,可以简单的认为是这个时间段内的平均值。基于这三个值,我们可以了解系统负载如何随时间变化。比如现在系统出了问题,你查看这三个值,发现1分钟的负载值比15分钟的负载值小很多,那么你可能错过了时间点系统出错了。在上面的示例中,平均负载显示1分钟为30,与15分钟的19相比有了很大的增加。负载增加的原因有很多,也许是CPU不够用;vmstat或mpstat可以进一步确认问题出在哪里。2.dmesg|尾巴$dmesg|尾部[1880957.563150]perlinvokedoom-killer:gfp_mask=0x280da,order=0,oom_score_adj=0[...][...][...][1880957.563400],anon-rss:1953348kB,file-rss:0kB[2320864.954447]TCP:PossibleSYNfloodingonport7001.Droppingrequest.CheckSNMPcount这个命令显示最新的系统日志。这里我们主要是看是否有一些系统错误会导致性能问题。上面的示例包括oom-killer以及TCP丢弃。不要跳过这一步!dmesg总是值得一看。3.vmstat1$vmstat1procs--------内存------------swap--------io-----system--------cpu-----rbswpdfreebuffcachesisobiboincsussyidwast3400200889792737085918280005610961300320020088992073708591860000592132844282981100320020089011273708591860000095012154991000320020088956873712591856000481190024599900003200200890208737125918600000158984840981100^Cvmstat展示了虚拟内存、CPU的一些情况。The1inthecommandlineintheaboveexamplemeanstodisplayevery1second.在这个版本的vmstat中,第一行表示的是本次启动以来的各种指标,我们可以暂时忽略第一行。需要查看的指标:r:处于可运行状态的任务,包括正在运行的任务和等待运行的任务。该值比平均负载更能指示CPU饱和度。这个值不包括等待io相关的任务。当r的值大于当前的CPU数量时,系统处于饱和状态。free:可用内存大小(以KB为单位)。si,so:换入和换出内存页。如果这两个值不为零,则表示内存不足。us,sy,id,wa,st:CPU时间的各种指标(取所有CPU的平均值),分别代表:用户态时间、内核态时间、空闲时间、等待io、窃取时间(在虚拟化环境下)其他租户的系统开销)将用户态CPU时间(us)和内核态CPU时间(sy)相加,可以进一步确认CPU是否繁忙。如果IO等待时间(wa)高,说明磁盘是瓶颈;注意这个也算在空闲时间(id)中,此时CPU也空闲,此时任务阻塞在磁盘IO上。你可以把等待IO的时间(wa)看作是CPU空闲的另一种形式,它告诉你CPU空闲的原因。系统在处理IO时,肯定会消耗内核时间(sy)。如果内核态时间过长,比如超过20%,我们需要进一步分析,可能是内核对IO的处理效率不高。在上面的例子中,大部分CPU时间都消耗在用户态,说明应用层代码主要是在使用CPU。CPU利用率(us+sy)也超过90%,不一定是问题;我们可以通过r和CPU计数来确定CPU饱和度。4.mpstat-PALL1$mpstat-PALL1Linux3.13.0-49-generic(titanclusters-xxxxx)07/14/2015_x86_64_(32CPU)07:38:49PMCPU%usr%nice%sys%iowait%irq%soft%steal%guest%gnice%idle07:38:50PMall98.470.000.750.000.000.000.000.000.000.7807:38:50PM096.040.002.970.000.000.000.000.000.000.9907:38:50PM197.000.001.000.000.000.000.000.000.002.0007:38:50PM298.000.001.000.000.000.000.000.000.001.0007:38:50PM396.970.000.000.000.000.000.000.000.003.03[…]这个命令打印出每个CPU的时间,可以看到CPU处理任务的方式是不是统一的.例如,如果单个CPU使用率很高,则说明这是一个单线程应用程序。5.pidstat1$pidstat1Linux3.13.0-49-generic(titanclusters-xxxxx)07/14/2015_x86_64_(32CPU)07:41:02PMUIDPID%usr%system%guest%CPPUCPUCommand07:41:03PM090.000.940.000.941rcuos/007:41:03PM042145.665.660.0011.3215mesos-slave07:41:03PM043540.940.940.001.898java07:41:03PM065211596.231.890.001598.1127java07:41:03PM065641571.707.550.001579.2528java07:41:03PM60004601540.944.720.005.669pidstat07:41:03PMUIDPID%usr%system%guest%CPUCPUCommand07:41:04PM042146.002.000.008.0015mesos-slave07:41:04PM065211590.001.000.001591.0027java07:41:04PM065641573.0010.000.001583.0028java07:41:04PM10867181.000.000.001.000snmp-pass07:41:04PM60004601541.004.000.005.009pidstat^Cpidstat和top很像,不同的是它可以每隔一段时间打印一次,而不是像top一样每次都清屏。这个命令可以方便的查看进程可能的行为模式,也可以直接copy过去,这样可以很方便的记录下各个进程的运行状态随时间的变化。上面的例子表明有2个Java进程消耗了大量的CPU。这里的%CPU表示所有CPU的值,例如1591%表示Java进程消耗了差不多16个CPU。6.iostat-xz1$iostat-xz1Linux3.13.0-49-generic(titanclusters-xxxxx)07/14/2015x86_64(32CPU)avg-cpu:%user%nice%system%iowait%steal%idle73.960.003.730.030。0622.21Device:rrqm/swrqm/sr/sw/srkB/swkB/savgrq-szavgqu-szawaitr_awaitw_awaitsvctm%utilxvda0.000.230.210.184.522.0834.370.009.9813.805.422.440.09xvdb0.010.001.028.94127.97598.53145.790.000.431.780.280.250.25xvdc0.010.001.028.86127.79595.94146.500.000.451.820.300.270.26dm-00.000.000.692.3210.4731.6928.010.013.230.713.980.130.04dm-10.000.000.000.940.013.788.000.33345.840.04346.810.010.00dm-20.000.000.090.071.350.3622.500.002.550.23iostat是了解块设备(磁盘)当前负载和性能的重要工具。几个指标的含义:r/s,w/s,rkB/s,wkB/s:每秒读取次数,每秒写入次数,每秒读取数据量,每秒写入数据量系统发送给设备的数量。这些指标反映了系统的工作量。系统的性能问题很可能是负载太大。await:系统向IO设备发送请求的平均响应时间。这包括请求排队的时间和处理请求的时间。超过经验值的平均响应时间表明设备已经饱和,或者设备有问题。avgqu-sz:设备请求队列的平均长度。队列长度大于1表示设备已饱和。%util:设备利用率。设备的繁忙程度表示设备在每一秒内处理IO所花费的时间比例。利用率大于60%通常会导致性能问题(见await),但每个设备都不同。利用率接近100%表示磁盘已饱和。如果块设备是逻辑块设备,逻辑快设备后面有很多物理磁盘,100%利用率只能说明某些IO处理时间达到了100%;后端物理磁盘可能远未饱和,可以处理更多负载。需要注意的另一件事是,磁盘IO性能不佳并不一定意味着应用程序存在问题。应用程序可以通过多种方式执行异步IO而不会阻塞IO;应用程序还可以使用预读和写缓冲等技术来减少IO延迟对自身的影响。7.free-m$free-mtotalusedfreesharedbufferscachedMem:245998245452214538359541-/+buffers/cache:23944222053Swap:右边两列显式:buffers:buffercacheforblockdeviceI/O。cached:文件系统的页面缓存。我们只想检查这些非零大小,这会导致更高的磁盘I/O(已通过iostat确认)和更差的性能。上面的例子看起来不错,每列有很多M大小。与第一行相比,-/+buffers/cache提供的内存使用情况会更加准确。Linux会把暂时不用的内存作为缓存,应用需要的时候再重新分配。所以用作缓存的部分内存实际上是空闲内存。为了解释这一点,甚至有人建了一个网站:http://www.linuxatemyram.com/。如果您使用的是ZFS,这可能会有点混乱。ZFS有自己的文件系统缓存,用free-m看不到;系统似乎没有太多可用内存,但ZFS可能有大量可用缓存。8.sar-nDEV1$sar-nDEV1Linux3.13.0-49-generic(titanclusters-xxxxx)07/14/2015_x86_64_(32CPU)12:16:48AMIFACEErxpck/stxpck/srxkB/stxkB/srxcmp/stxcmp/srxmcst/s%ifutil12:16:49AMeth018763.005032.0020686.42478.300.000.000.000.0012:16:49AMlo14.0014.001.361.360.000.000.000.0012:16:49AMdocker00.000.000.000.000.000.000.000.0012:16:49AMIFACErxpck/stxpck/srxkB/stxkb/srxcmp/stxcmp/srxmcst/s%ifutil12:16:50AMETH019763.005101.0021999.10482.560.000.000.000.000.000.000.000.000.0012:16:16:16:50AMLO20.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.00012;这个工具可以查看网络接口的吞吐量:rxkB/s和txkB/s可以测量负载,也可以查看是否达到了网络流量限制。在上面的例子中,eth0的吞吐量达到了22Mbytes/s左右,差不多是176Mbits/sec,远小于1Gbit/sec。此示例还包含%ifutil标记设备利用率,我们也使用Brenan的nicstat工具对其进行测量。和nicstat一样,这个设备利用率很难正确测量,而且在上面的例子中这个值似乎也存在一些问题。9.sar-nTCP,ETCP1$sar-nTCP,ETCP1Linux3.13.0-49-generic(titanclusters-xxxxx)07/14/2015_x86_64_(32CPU)12:17:19AMactive/spassive/siseg/soseg/s12:17:20AM1.000.0010233.0018846.0012:17:19AMatmptf/sestres/sretrans/sisegerr/sorsts/s12:17:20AM0.000.000.000.000.0012:17:20AMactive/spassive/siseg/soseg/s12:17:21AM17:020AM17:020/sestres/sretrans/sisegerr/sorsts/s12:17:21AM0.000.000.000.000.00^C这是TCP重要指标的总结,包括:active/s:TCPconnectionsactivelyopenedlocallypersecond,即本地程序使用connect()系统调用passive/s:每秒从源发起的TCP连接,即本地程序使用accept()接受的连接retrans/s:每秒TCP重传次数active和passive通常可以用来衡量服务器的负载:接受连接数(被动),下游连接数(主动)。你可以简单的认为active是来自host的连接,passive是来自host的连接;但这并不是一个非常严格的说法,比如loalhost和localhost之间的连接。重新传输表示网络或服务器问题。可能是网络不稳定,也可能是服务器过载,开始丢包。上面的例子意味着每秒只建立1个新连接。10.top$toptop-00:15:40up21:56,1user,loadaverage:31.09,29.87,29.92Tasks:871total,1running,868sleeping,0stopped,2zombie%Cpu(s):96.8us,0.4sy,0.0ni,2.7id,0.1wa,0.0hi,0.0si,0.0stKiBMem:25190241+total,24921688used,22698073+free,60448buffersKiBSwap:0total,0used,0free.554208cachedMemPIDUSERPRNIVIRTRESSHRS%CPU%MEMTIME+COMMAND20248root2000.227t0.012t18748S30905.229812:58java4213root20027225446464044232S23.50.0233:35.37mesos-slave66128titancl+2002434423321172R1.00.00:00.07top5235root20038.227g54700449996S0.70.22:02.74java4299root20020.015g2.682g16836S0.31.133:14.42java1root2003362029201496S0.00.00:03.82init2root200000S0.00.00:00.02kthreadd3root200000S0.00.00:05.35ksoftirqd/05root0-20000S0.00.00:00.00kworker/0:0H6root200000S0.00.00:06.94kworker/u256:08root200000S0.00.02:38.05rcu_schedtop命令涵盖了我们之前介绍的许多指标。我们可以用它来查看与我们之前检查的结果是否有很大差异。如果是这样,则意味着系统上的负载正在发生变化。top的缺点是很难找到这些指标随时间变化的一些行为模式。在这种情况下,提供滚动输出的命令(例如vmstat或pidstat)是更好的方法。如果你没有足够快地暂停输出(Ctrl-S暂停,Ctrl-Q继续),一些间歇性问题的线索也可能因为被清除而丢失。后续分析有更多的命令和方法可以用于更深入的分析。查看Velocity2015中Brendan的Linux性能工具教程,其中包括40多个命令,涵盖可观察性、基准测试、调优、静态性能调优、分析和跟踪。我们的爱好之一是处理整个网络规模的系统可靠性和性能问题。