第02章 服务器为什么这么慢?耗尽了CPU、RAM和磁盘I/O资源

        尽管服务器的绝大部分问题都与网络有关,但是还有一类问题仅与本地服务器相关。让这个问题变得棘手的是:本地服务器问题和网络问题经常表现出相同地征兆。事实上,服务器本地的问题会导致网络问题,而将影响网络的问题留到第五章介绍。
        几乎DevOps团队中的所有成员都遇到过性能不好或响应缓慢的主机,不论是试图查出问什么最近一次提交比之前慢很多的开发者,在代码部署到生产环境之前努力执行负载测试的QA工程师,还是需要确定是否应该购买更多RAM、CPU或运行速度更快的磁盘的系统管理员。这些技术甚至可以帮你排除Linux桌面系统中的负载问题。
        关于主机最常见的一个问题可能是性能太差,甚至都无法响应。通常,网络故障会引发这个问题,但本章将会介绍一些本地排除故障的工具,借助这些工具可以分辨出网络过载和机器过载之间的区别。
        机器运行缓慢通常是由于消耗了太多系统特定的资源。系统的主要资源包括CPU、RAM、磁盘I/O以及网络(将在第五章介绍)。过度使用这些资源的任何一种就都会让系统陷入困境,此时唯一的解决方法就是——重启。不过如果能登录到系统之中,则可以借助大量工具确定问题的起因。
 
2.1    系统负载
        解决引起系统运行缓慢的问题时,平均系统负载可能时最先用到的基本度量标准。在排除系统运行缓慢的问题时,通常我执行的第一条命令时uptime:
            $ uptime
            13:35:03 up 103 days, 8min, 5 users, load average: 2.03, 20.17, 15.09
        load average 后面的三个数子 2.03、20.17和15.09分别代表了1分钟、5分钟和15分钟内机器的平均负载。一个系统的平均负载等于处于运行或者不可打扰状态进程的平均数。可运行的进程要么正在使用CPU,要么正在等待使用CPU;不可打扰状态的进程都在等待I/O响应。
        平均负载为1的单CPU系统以为这个CPU处于恒定负载。如果单CPU系统的平均负载是4,那么这个系统平均处于它可承受负载能力的4倍,所以3/4的进程都在等待资源。一个系统的平均负载不会因为你所拥有的CPU数量而更改,所以,如果具备两个CPU的系统平均负载是1,那么其中一个CPU一直处于满负荷状态,也就是说系统处于50%的负载状态。所以,负载状态为1的单CPU系统与负载状态为1的单CPU系统与负载状态为4的四CPU系统使用资源的量一样。
        1分钟、5分钟、15分钟、的平均负载描述了相对时间内的平均负载会让你对系统当前所处的状态有一个清晰的认识,所以在前面这个例子中,你能看到服务器在过去的1分钟内负载为2,但是在国储的5分钟内平均负载却飙升到了20。前15分钟内处于高负载的状态,而且5分钟前系统负载又开始增长,但是现在已经减弱。让我们将它与一个完全不同的平均负载做个对比。
            $ uptime
            05:11:52 up 20 days, 5min, 2 users, load average: 17.29, 0.12, 0.01
        在这个例子中,5分钟内和15分钟内的平均负载都很低,但是1分钟内的平均负载却很高,所以我知道负载的飙升相对而言发生在最近。在这种情况下,通常我会连续多次运行uptime命令(或者使用top命令,马上我就会讲到这个工具)来观察负载是持续上升还是正在下降。
 
什么是高平均负载
        一个值得研究的问题是:平均负载多少算高?简单的回答是“这取决于产生高负载的原因”。因为负载描述了正在使用资源的活动进程的平均数量,所以负载的飙升透露了很多信息。明确负载是CPU密集型(等待CPU资源的进程)、RAM密集型(争夺磁盘或网络I/O资源的进程)非常重要。
        例如,如果运行的一个应用程序在不同的时间点产生大量的同步线程,这些线程会同时启动,你可能会看到负载飙升到20、40或者更高,他们在竞争系统资源。随着这些进程逐渐完成,负载就会降下来。通常CPU密集型的系统会比I/O密集型的系统响应度更高。我见过数以百计CPU密集型的系统,我仍然可以在这些系统上运行故障排除工具而且具有良好的响应时间。我也见过I/O负载相对较低的I/O密集型系统,只是登录这些系统就需要花费一段时间,因为它们的磁盘I/O完全饱和了。用尽RAM资源的系统通常与I/O密集型的系统表现相同,因为一旦系统开始使用磁盘上的交换存储,它就会消耗磁盘资源,导致进程逐渐变慢直至停止。
        
2.2    使用top命令解决负载问题
        当需要解决高负载问题的时候,我第一个想到的工具是top命令。在命令行输入Top命令并按下Enter键后,马上就能看到大量的系统信息如图👇。
这些数据都会不断更新,所以你能看到系统中总共有多少进程正在运行、总共有多少内存、使用了多少内存、还剩多少内存,最后还包含系统的进程列表以及它们占用的资源数量。使用TOP命令可能无法看到系统当前运行的所有进程,因为无法将它们都显示在屏幕上。TOP命令默认排序方式是按照进程的CPU使用情况从上到下排序,所以可以一眼就能看到哪些进程正在消耗CPU资源。
        那么如果发现一个进程占用了全部CPU资源,你想要终止这个进程,该怎么做呢?top命令输出的第一列是PID,它代表程序的进程ID——系统赋给每个进程的唯一ID。想要终止某个进程,只需要按下K按键,然后输入想要终止的PID,最后当系统提示该进程将会终止于signal 15时,按下Enter键即可。
        默认情况下top命令在非交互式模式下运行,如果不需要看显示在屏幕外的信息,那一切都还好。如果想要看top命令的完整输出,或者想将这些信息都重定向到文件中,那么你可以在批处理模式下运行这个命令。-b选项可以开启批处理模式,-n选项可以控制在推出top命令之前,刷新信息多少次。例如,想看到完整的输出,仅需运行一次top命令,输入如下命令:
            $ top -b -n 1
    如果想要将这些信息存储到名为top_output的文件中,那么请输入如下命令:
            $ top -b -n 1 >top_output
    如果想要查看top命令的输出,同时将该输出写入文件,那么你可以使用便捷的命令行工具tee:
            $ top -b -n 1 | tee top_output
2.2.1 了解top命令的输出
        使用top命令来排除系统负载问题时,基本步骤时检查top的输出,借此明确耗尽了那些资源(CPU、RAM还是磁盘I/O)。一旦清楚了这个问题,就可以尝试检查到底是那些进程大量消耗了这些资源。首先,检查系统中top命令的标准输出:
        
        
                top命令输出的第一行与你之前见到的uptime命令的输出一致。正如你在这个例子中看到的,对于这台拥有4个CPU的机器来说,系统负载并不大。
            top -14:08:25 up 38 days, 1 user, load average: 1.70,1.77,1.68
        不过除了标准的系统负载,top命令还为你提供了额外的度量标准。例如,cpu(s)这一行提供了当前CPU运行情况的信息:
            
        如果你不清楚这些缩写代表什么,那么他们对你毫无意义,所以我将他们都列在下面:
            us:用户CPU时间
            运行非优雅的用户进程所占CPU时间的百分比(优雅,英文“nicing”,是指一个进程允许你根据其他进程更改优先级)。
            sy:系统CPU时间
            运行内核和内核进程所占CPU时间的百分比
            ni:优雅CPU时间
            如果更改过一些进程的优先级,这个指标能够告诉你他们所占CPU时间的百分比。
            id:CPU空闲时间
            这是你希望具备很高的度量指标中的一个。它代表了CPU的空闲时间比。如果系统运行缓慢,但是这个指标特别高,那么你就可以确定问题的原因不是高CPU负载。
            wa:I/O等待
            这个数子代表了CPU时间用在等待执行I/O操作所占的百分比。当你解决运行缓慢的系统问题的时候,这是一个非常有价值的度量指标,因为如果这个数值很低,那么就能轻松排除磁盘或者网络I/O的问题。
            hi:硬件中断
            CPU用于处理硬件中断所占时间的百分比。
            si:软件中断
            CPU用在处理软件中断所占时间的百分比。
            st:流逝的时间
             如果你正在运行虚拟机,这个度量指标会告诉你虚拟机中执行的其它任务所占cpu时间的百分比。
        在前面的例子中,你可以看到系统有超过50%的空闲时间,这与机器具备4个CPU、系统负载为1.70的指标相匹配。当你处理一个运行缓慢的系统的时候,首先要观察的度量指标之一就是I/O等待时间,它可以用来排除磁盘I/O的问题。如果I/O等待时间很低,那么可以看看CPU空闲时间百分比;如果I/O等待时间很高,那么下一步就是确定是什么因素导致I/O等待时间所占的比重这么高,这一点我马上就会讲到。如果I/O等待和CPU空闲时间百分比都很低,那么很可能会看到一个非常高的用户时间百分比,所以你必须确定是什么原因导致了这么高的用户时间百分比。如果I/O等待时间所占百分比很低,而空闲时间百分比很高,那么你就知道系统运行缓慢不是CPU资源的原因,而应该从别的地方找原因。这可能意味着应该查看网络问题或者web服务器的问题,或者查看Mysql查询缓慢的问题等。
 
2.2.2    解决高用户时间的问题
        解决故障的过程中一个常见而又相对简单得问题是,由用户CPU时间百分比高引起的负载问题。这很常见,因为服务器上的服务很可能会占系统负载的绝大部分,而且这些服务都是用户进程。如果发现用户时间百分比高单I/O等待时间百分比却很低,很显然你需要确定系统中哪一个进程占用了如此大量的CPU资源。默认情况下,top命令会按照各个进程cpu使用率由高到低排序。
            
            在这个例子中mysqld进程消耗了53%的cpu时间,nagios2db_status进程消耗了12%的cpu时间。注意,这个数子代表的是所占单个cpu的百分比,所以如果你拥有一台具备4个CPU的机器,可能会看到多个进程都消耗了99%的CPU时间。
        你会看到大部分高CPU负载的情况都是由于CPU被一个、两个或者很多个进程消耗殆尽。任何一种情况都很容易确定,因为在第一种情况下,top命令输出中前一两个进程都有非常高的CPU百分比,而其余进程所占CPU百分比相对很低,此时,解决方法就是终止大量使用CPU资源的进程(按K键,然后输入对应进程的PID)。
        在多进程情况下,你可能让系统做了太多事。比如说,在web服务器中可能有大量的Apache进程,还有cron中运行的部分日志解析脚本。这些进程可能会消耗差不多等量的CPU资源。这种问题的解决方案从长期来看相当复杂。以WEB服务器为例,你的却需要运行全部Apache进程,同时你可能还需要日志解析工具。在短期内,你可以终止(或推迟)一些进程知道负载降低,但是从长期来看,你可能需要考虑增加系统资源或者将这些功能分拆到多台服务器上。
 
2.2.3    解决内存不足的问题
        top输出中的以下两行提供了非常有价值的RAM使用情况的信息。在处理特定系统问题之前,排除内存问题非常重要。
            
        第1行告诉我们有多少物理内存可用、占用了多少内存、空闲多少内存以及缓存了多少内存。第2行为我们提供了相似的信息,交换存储以及Linux文件缓存使用了多少RAM。一眼看上去会以为系统内存快要耗尽了,因为系统仅显示有26768KB空闲内存。不少故障排除人员都会被输出中与Linux文件缓存相关的已用和空闲的信息误导。一旦linux将一个文件载入到RAM中,当程序用完这个文件的时候,不需要将它从RAM中移除。如果还有可用的RAM,Linux将会在RAM中缓存这个文件,这样如果一个程序再次访问这个文件,访问速度江湖i得到大幅提升。如果系统的确需要为活动的进程提供RAM,那RAM中将不会缓存这么多文件。由于文件缓存的蹲在,通常在服务器运行相当长的一段时间后,都会显示仅有多少量RAM空闲,而其余的都被缓存占用。
        想要找出进程到底真正使用了多少RAM,你必须刨除RAM中的文件缓存。正如你所看到的示例代码一样,在已用的997408KB的RAM中,有286040KB的RAM被文件缓存占用,系统仍然有大量可用的内存资源,几乎没有使用任何交换存储。即便你的确看到使用了一些交换存储,这也不足以作为问题的征兆。如果一个进程转为空闲状态,Linux通常会将它占用的RAM释放,供其他进程使用。辨别是否耗尽了RAM的一个好方法是查看文件缓存。如果实际用的内存减去文件缓存的值很大,同时交换存储的值也很高,很肯恩恶搞的确有内存问题。
        如果真的发现了内存问题,下一步就是确定哪些进程消耗了RAM。top默认按照CPU的使用率排序,所以你需要将其改为按照RAM使用率来排序。保持TOP的打开状态,然后按下M键。这就会让所有进程按照RAM的使用率排序。
            
            
        注意%MEM这一列,会看到前几个进程占用了大量RAM。如果你找到了大量使用RAM的进程,可以终止它们,或者根据程序,通过专门的故障排除方法来寻找是什么原因导致这些进程占用了大量RAM。
    注意:
        实际上TOP命令的输出可以根据任何列排序。想要更改Top输出的排序方式,按F键进入选择排序列的界面。再按下对应特定列的按键之后(比如,K对应CPU列),再按Enter键就能回到TOP的输出界面。
        Linux内核也有一个内存耗尽(OOM)终结者就会开始终止进程。有些情况下,终止的可能是占用大量RAM的进程,但它并不能保证不会终止未战用大量RAM的进程,有的时候它也会终止像sshd这样的程序或者其他进程,而不是真正的罪魁祸首。很多时候,OOM终止了一些进程之后,系统就会变得不大稳定,所以你不得不重启机器以确保所有的系统进程都在正常运行。如果OOM终结者介入了,在/var/log/syslong中你会看到如下行:
            
        
 2.2.4    解决高I/O等待时间问题
        当你看到I/O等待时间所占CPU时间的比重很高的时候,首先需要检查的就是机器是否正在大量使用交换空间。因为硬盘操作的速度远远低于RAM,所以当系统内存耗尽,开始使用交换空间的时候,系统的性能会受到严重影响。任何想要访问硬盘的操作都要完成与硬盘的I/O交换。所以,故障派出的第一步是看内存是都耗尽,如果是,先解决这个问题。如果还有大量可用的RAM,你需要明确哪个进程占用了大部分I/O操作。
        有的时候很难弄明白到底是哪个进程占用了大量的I/O资源,但是如果系统中存在多个分区,你可以缩小范围,找到那个分区正在执行大量I/O操作。想要做到这一点,需要使用iostat程序。如果你的机器没有安装,可以通过包装管理工具来安装。
        在解决问题之前,你最好先安装好这个程序。安装了这个程序后,就可以不带任何参数运行iostat,观察系统的整体情况。
            
        首先看到的是Top命令相似的CPU信息,下面紧跟着系统上所有硬盘设备及其分区的I/O状态信息。下面是各列代表的意义:
            tps:
            这个值列出了设备每秒的传输量。“传输”(Transfer)是向设备发送I/O请求的另一种表达方式。
            Blk_read/s
            表示每秒从设备读取的数据量。
            Blk_wrth/s
            表示每秒向设备写入的数据量。
            Blk_read
            这一列表示从设备读取的数据总量
            Blk_wrtn
            这一列表示写入设备的总数据量。
        当系统处于高I/O负载状态的时候,首先就是观察每个分区,看看那个分区的I/O负载最高。比如说,你有一台数据库服务器,数据库本身存储在/dev/sda3分区。你如果看到大量的I/O操作来自这里,这就是一个很好的线索:数据库很可能占用了大量I/O资源。
        弄明白这一点后,下一步就是确定I/O操作大部分来自读取还是写入。假设你怀疑备份工作导致了I/O操作的增长。因为备份工作的操作主要集中于从文件系统中读取文件,然后通过网络传输到备用服务器,如果大量的I/O操作都来自于写入而不是读取操作,那么大概可以排除这个问题。
    注意:
        你可能需要iostat命令多次,一次得到系统当前的精确I/O状况。如果在命令行指定一个数字参数,iostat就会持续运行并根据指定的描述刷新输出信息。比如说,如果你想要每2秒看到一次iostat的输出,就可以输入sudo iostat 2。如果你有任何NFS共享,iostat另一个非常有用的参数是-n,当你指定了-n参数,iostat就会给出所有NFS共享的I/O统计信息。
        除了iostat,在最新的发布版中,我们还有一个很简单的工具。实际上,它是top和iostat程序的混合体,能够显示系统中所有运行进程并将进程根据I/O统计信息排序。这个软件使用了Linux内核的一些新特性,所以需要2.6.20或者更新的内核。如果默认情况下没有安装这个程序,那么可以在iotop包中找到它。这个工具包含在基于Debian的版本中,但是对于基于Red Hat的版本来说,你就需要在网上或者从第三方残酷中寻找并安装第三方的RPM。安装了这个包后,就可以用root权限运行iotop,并看到如下输出:
            
        在这个例子中,你会看到rsync进程执行了大量I/O读取操作。
 
2.3    问题发生后的高负载处理
        截止到这里,本章都在讨论当系统负载过高的时候,如何找到高负载的原因。尽管top和iostat都是非常优秀的工具,但是当系统发生问题的时候,我们不是总能足够幸运地找到解决办法。我记不清我遇到过多少次机器运行缓慢,只能等待负载降低才能登录。只需要稍微多做一点工作,就饿能在服务器上安装相应的工具,记录全天地性能数据。
        我们已经讨论了如何使用sysstat包中地iostat工具来解决高I/O地问题,不过sysstat中也包含一些能报告CPU和RAM使用情况地工具。虽然的却可以使用top命令达到这个目的,但是sysstat更加强大,他能够用一种简单地机制来记录系统地统计信息,如CPU负载,RAM以及I/O状态。借助这些统计信息,当有人抱怨昨天中午系统很慢是,你就可以查看日志,看看是什么原因引起地这个问题。
 
2.3.1        配置sysstat
        第一步是使用包管理工具安装sysstat包。在Debian的系统(如Ubuntu)中,sys stat不会自动启用,所以需要修改/etc/defaylt/sysstat文件,将
        在基于Red Hat的系统上你可能需要修改/etc/sysconfig/sysstat文件,更改HISTORY选项,让他可以记录7天以上的统计信息。对于这两种系统,统计信息都可以每10分钟抓取一次并记录每日总结。
        一旦启用了sysstat,他就会每10分钟手机一次系统状态并将它们存储到/var/log/sysstat或/var/log/sa文件中。除此之外,每天晚上在午夜之前,它们还会分割统计文件。这些操作都是由/etc/cron.d/sysstat脚本执行的,所以如果想要更改sysstat收集信息的频率,你可以修改这个脚本文件。
 
2.3.2        查看CPU统计信息
        sysstat统计信息的时候,他将这些信息存储在以sa开头、以本月当前日期结尾的文件名的文件中(如sa03)。这就意味着你可以查看从当前日期起,一个月以内的统计数据。使用sar工具可以查看这些统计信息。默认情况下sar会输出当天的CPU统计信息:
            
              
从输出中可以发现,CPU的很多统计信息都和top命令的输出相同。在最后一行,sar还未每个值提供了平均值。
 
2.3.3        查看RAM统计信息
        sysstat计划任务不仅可以收集CPU负载信息,还能收集很多别的信息。例如,使用-r选项就可以收集RAM的统计信息:
            
        在这里可以看到使用了多少内存,空闲多少内存,同时还能查看交换空间的信息以及文件缓存的信息,这些信息与top或free命令输出的信息类似。与之不同的是,你可以及时查看之前的信息。
 
2.3.4        查看磁盘统计信息
        从sar中还可以获得另一个非常有用的度量指标:磁盘统计信息。使用-b选项能给出一些列磁盘I/O的基本信息。
            
            
        从这里可以看到每秒总共传输的数据量(tps),它由总共读取的数据量和写入的数据量(分别是rtps和wtps)相加获得。bread/s列并非用来衡量块I/O,而是告诉你平均每秒读取的数据量。类似地,bwrtn/s能告诉你平均每秒写入的数据量。
        sar程序可以传入很多参数,输出特定的数据集,不过有的时候你可能想一次性看到所有数据。使用-A选项可以做到这点。他会显示包括负载平均值、CPU负载、RAM、磁盘I/O、网络I/O和其他一些有趣值在内的统计信息。这样可以让你更加了解sar能够输出什么统计信息,之后,通过阅读sar的用户手册(输入man sar),可以了解到想到看特定的统计信息因该传入什么标志位。
 
2.3.5        查看之前的统计信息
        当然,到目前为止,我仅仅介绍了如何查看整天的信息。优势你会只想查看一天中部分时间段内的信息。想要获得指定时间范围内的信息,可以使用-s和-e参数分别制定你感兴趣的开始时间和结束时间。例如,如果想要查看8:00pm—8:30pm这个时间段内的cpu数据,需要输入:
            
            
        如果想要获取非当天的数据,使用-f选项,后面输入存储在/var/log/sysstat或/var/log/sa文件夹内统计信息文件的完整路径。例如,想要获取本欲第6天的统计信息,你需要输入:
            $    sar -f /var/log/sysstat/sa06
        也可以正常混合使用任意其它sar选项,从而获得特定类型的统计信息。
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
posted @ 2020-12-24 14:00  陌丶言  阅读(148)  评论(0)    收藏  举报