备注:该内容是摘自《DevOps故障排除:Linux服务器运维最佳实践》一书
系统负载
解决引起系统运行缓慢的问题时,平均系统负载可能是最先用到的基本度量标准。在排除系统运行缓慢的问题时,通常我执行的第一条命令是uptime:
load average后面的3个数字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系统与负载状态为4的四CPU系统使用资源的量一样。
1分钟、5分钟、15分钟的平均负载描述了相对时间内负载的平均值,这些值在确定系统当前状态时非常有用。1分钟内的平均负载会让你对系统当前所处 的状态有一个清晰的认识,所以在前面这个例子中,你能看到服务器在过去的1分钟内负载为2,但是在过去的5分钟内平均负载却飙升到了20。前15分钟内, 负载平均值是15。由此可知,机器在过去的15分钟内处于高负载的状态,而且5分钟前系统负载又开始增长,但是现在已经减弱。让我们将它与一个完全不同的 平均负载做个对比。
在这个例子中,5分钟内和15分钟内的平均负载都很低,但是1分钟内的平均负载却很高,所以我知道负载的飙升相对而言发生在最近。在这种情况下,通常我会连续运行多次uptime命令(或者使用top命令)来观察负载是持续上升还是正在下降
2.什么是高平均负载?
一个值得研究的问题是:平均负载多少算高?简单的回答是“这取决于产生高负载的原因”。因为负载描述了正在使用资源的活动进程的平均数量,所以负载 的飙升透露了很多信息。明确负载是CPU密集型(等待CPU资源的进程)、RAM密集型(尤其是,频繁使用的RAM被移入了交换区)还是I/O密集型(争 夺磁盘或网络I/O资源的进程)非常重要。
例如,如果运行的一个应用程序在不同的时间点产生大量的同步线程,这些线程会同时启动,你可能会看到负载飙升到20、40或者更高,它们在竞争系统资源。随着这些进程逐渐完成,负载就会降下来。
通常CPU密集型的系统会比I/O密集型的系统响应度更高。我见过数以百计CPU密集型的系统,我仍然可以在这些系统上运行故障排除工具而且具有良 好的响应时间。我也见过I/O负载相对较低的I/O密集型系统,只是登录这些系统就需要花费一段时间,因为它们的磁盘I/O完全饱和了。用尽RAM资源的 系统通常与I/O密集型的系统表现相同,因为一旦系统开始使用磁盘上的交换存储,它就会消耗磁盘资源,导致进程逐渐变慢直至停止。
3.使用top命令解决负载问题
当需要解决高负载问题的时候,我第一个想到的工具是top命令。在命令行输入top命令并按下Enter键后,马上就能看到大量的系统信息(见图 2-1)。这些数据都会不断更新,所以你能看到系统的实时信息,包括系统启动了多久、负载平均值、系统中总共有多少进程正在运行、总共有多少内存、使用了 多少内存、还剩多少内存,最后还包含系统的进程列表以及它们占用的资源数量。使用top命令可能无法看到系统当前运行的所有进程,因为无法将它们都显示在 屏幕上。top命令默认排序方式是按照进程的CPU使用情况从上到下排序,所以可以一眼就能看到哪些进程正在消耗CPU资源。
那么如果发现一个进程占用了全部CPU资源,你想要终止这个进程,该怎么做呢?top命令输出的第一列是PID,它代表程序的进程ID―系统赋给每 个进程的唯一ID。想要终止某个进程,只需按下K按键,然后输入想要终止的PID,最后当系统提示该进程将会终止于signal 15时,按下Enter键即可。
默认情况下top命令在非交互式模式下运行,如果不需要看显示在屏幕外的信息,那一切都还好。如果想要看到top命令的完整输出,或者想将这些信息 都重定向到文件中,那么你可以在批处理模式下运行这个命令。-b选项可以开启批处理模式,-n选项可以控制在退出top命令之前,刷新信息多少次。例如, 想看到完整的输出,仅需运行一次top命令,输入如下命令:
如果想要将这些信息存储到名为top_output的文件中,那么请输入如下命令:
如果想要查看top命令的输出,同时将该输出写入文件,那么你可以使用便捷的命令行工具tee:
使用top命令来排除系统负载问题时,基本步骤是检查top的输出,借此明确耗尽了哪些资源(CPU、RAM还是磁盘I/O)。一旦清楚了这个问题,就可以尝试检查到底是哪些进程大量消耗了这些资源。首先,检查系统中top命令的标准输出:
top命令输出的第一行与你之前见到的uptime命令的输出一致。正如你在这个例子中看到的,对于这台拥有4个CPU的机器来说,系统负载并不大。
不过除了标准的系统负载,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查询缓慢的问题等。
4.解决高用户时间的问题
解决故障的过程中一个常见而又相对简单的问题是,由用户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进程,同时你可能还需 要日志解析工具。在短期内,你可以终止(或推迟)一些进程直到负载降低,但是从长期来看,你可能需要考虑增加系统资源或者将这些功能分拆到多台服务器上。
5.解决内存不足的问题
top输出中的以下两行提供了非常有价值的RAM使用情况的信息。在处理特定的系统问题之前,排除内存问题非常重要。
第1行告诉我们有多少物理内存可用、占用了多少内存、空闲多少内存以及缓存了多少内存。第2行为我们提供了相似的信息,交换存储以及Linux文件缓存使用了多少RAM。一眼看上去会以为系统内存快要耗尽了,因为系统仅显示有26 768KB空闲内存。不少故障排除人员都会被输出中与Linux文件缓存相关的已用和空闲的信息误导。一旦Linux将一个文件载入到RAM中,当程序用 完这个文件的时候,不需要将它从RAM中移除。如果还有可用的RAM,Linux将会在RAM中缓存这个文件,这样如果一个程序再次访问这个文件,访问速 度将会得到大幅提升。如果系统的确需要为活动的进程提供RAM,那RAM中将不会缓存这么多文件。由于文件缓存的存在,通常在服务器运行相当长的一段时间 后,都会显示仅有少量RAM空闲,而其余的都被缓存占用。
想要找出进程到底真正使用了多少RAM,你必须刨除RAM中的文件缓存。正如你所看到的示例代码一样,在已用的997 408KB的RAM中,有286 040KB的RAM被文件缓存占用,所以这就是说实际上仅使用了711 368KB的RAM。在这个例子中,系统仍然有大量可用的内存资源,几乎没有使用任何交换存储。即便你的确看到使用了一些交换存储,这也不足以作为问题的 征兆。如果一个进程转为空闲状态,Linux通常会将它占用的RAM释放,供其他进程使用。辨别是否耗尽了RAM的一个好方法是查看文件缓存。如果实际用 的内存减去文件缓存的值很大,同时交换存储的值也很高,很可能的确有内存问题。
如果真的发现了内存问题,下一步就是确定哪些进程消耗了RAM。top默认按照CPU的使用率排序,所以你需要将其改为按照RAM使用率来排序。保持top的打开状态,然后按下M键。这就会让所有进程按照RAM的使用率排序。
注意%MEM这一列,会看到前几个进程占用了大量RAM。如果你找到了大量使用RAM的进程,可以终止它们,或者根据程序,通过专门的故障排除方法来寻找是什么原因导致这些进程占用了大量RAM。
注意
实际上top命令的输出可以根据任何列排序。想要更改top输出的排序方式,按F键进入选择排序列的界面。在按下对应特定列的按键之后(比如,K对应CPU列),再按Enter键就能回到top的输出界面。
Linux内核也有一个内存耗尽(OOM)终结者,如果低内存导致系统运行危险,它就会介入。当系统内存快要耗尽的时候,OOM终结者就会开始终止 进程。有些情况下,终止的可能是占用大量RAM的进程,但它并不能保证不会终止未占用大量RAM的进程。有的时候它也会终止像sshd这样的程序或者其他 进程,而不是真正的罪魁祸首。很多时候,OOM终止了一些进程之后,系统就会变得不大稳定,所以你不得不重启机器以确保所有的系统进程都在正常运行。如果 OOM终结者介入了,在/var/log/syslog中你会看到如下行:
6.解决高I/O等待时间问题
当你看到I/O等待时间所占CPU时间的比重很高的时候,首先需要检查的就是机器是否正在大量使用交换空间。因为硬盘操作的速度远远低于RAM,所 以当系统内存耗尽,开始使用交换空间的时候,系统的性能会受到严重影响。任何想要访问硬盘的操作都要完成与硬盘的I/O交换。所以,故障排除的第一步是看 内存是否耗尽,如果是,先解决这个问题。如果还有大量可用的RAM,你需要明确哪个进程占用了大部分I/O操作。
有的时候很难弄明白到底是哪个进程占用了大量I/O资源,但是如果系统中存在多个分区,你可以缩小范围,找到哪个分区正在执行大量I/O操作。想要 做到这一点,需要使用iostat程序,基于Red Hat和基于Debian的系统的sysstat包中都提供了这个程序。如果你的机器没有安装,可以通过包管理工具来安装。
在解决问题之前,你最好先安装好这个程序。安装了这个程序后,就可以不带任何参数运行iostat,观察系统的整体情况。
首先看到的是与top命令相似的CPU信息,下面紧跟着系统上所有硬盘设备及其分区的I/O状态信息。下面是各列代表的意义:
tps
这个值列出了设备每秒的传输量。“传输”(Transfer)是向设备发送I/O请求的另一种表达方式。
Blk_read/s
表示每秒从设备读取的数据量。
Blk_wrtn/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读取操作。
7.问题发生后的高负载处理
截止到这里,本章都在讨论当系统负载过高的时候,如何找到高负载的原因。尽管top和iostat都是非常优秀的工具,但是当系统发生问题的时候, 我们不是总能足够幸运地找到解决办法。我记不清我遇到过多少次机器运行缓慢,只能等待负载降低才能登录。只需要稍微多做一点工作,就能在服务器上安装相应 的工具,记录全天的性能数据。
我们已经讨论了如何使用sysstat包中的iostat工具来解决高I/O的问题,不过sysstat中也包含一些能报告CPU和RAM使用情况 的工具。虽然的确可以使用top命令达到这个目的,但是sysstat更加强大,它能够用一种简单的机制来记录系统的统计信息,如CPU负载、RAM以及 I/O状态。借助这些统计信息,当有人抱怨昨天中午系统很慢时,你就可以查看日志,看看是什么原因引起的这个问题。