首页 > 代码库 > 服务器性能调优

服务器性能调优

转:http://blog.csdn.net/wj_j2ee/article/details/7987483

 

一 绪论

Linux性能监控之绪论篇性能调优的目的是找到系统的瓶颈,并且调节系统来设法消除这些瓶颈.我们在监控性能的时候重点在于监视一下子系统:
1.CPU
2.Memory
3.IO
4.Network

但这些系统都是彼此依赖,不能单独只看其中一个.当一个系统负载过重时往往会引起其它子系统的问题,比如说:
->大量的读入内存的IO请求(page-in IO)会用完内存队列;
->大量的网络流量会造成CPU的过载;
->CPU的高使用率可能正在处理空闲内存队列;
->大量的磁盘读写会消耗CPU和IO资源.

我们测试的系统,总的来说可分为二类:
第一, IO Bound, 这类系统会大量消耗内存和底层的存储系统,它并不消耗过多的CPU和网络资源(除非系统是网络的).IObound系统消耗CPU资源用来接受IO请求,然后会进入休眠状态.数据库通常被认为是IO bound系统.

第二, CPU Bound,这类系统需要消耗大量的CPU资源.他们往往进行大量的数学计算. 高吞吐量的Web server,Mail Server通常被认为是CPU Bound系统.

在性能测试中首先要做的是建立基线(Baseline),这样后续的调整才会有一个参考标准.值得注意的是,在测试基线的时候,一定要保证系统工作在正常的状态下.

在Linux上,监视系统的性能的常用工具有:
Tool    Description                               Base            Repository
vmstat all purpose performancetool                yes             yes
mpstat provides statistics perCPU                 no              yes
sar all purpose performance monitoringtool        no              yes
iostat provides diskstatistics                    no              yes
netstat provides networkstatistics                yes             yes
dstat monitoring statisticsaggregator             no              inmost distributions
iptraf traffic monitoringdashboard                no              yes
ethtool reports on Ethernet interface configurationyes            yes

这些工具在Linux的安装过程中都可以选择进行安装。

下面是一个vmstat产生的baseline的例子:
# vmstat 1
procs memory swap io system cpu
r b swpd free buff cache si so bi bo in cs us sy wa id
1 0 138592 17932 126272 214244 0 0 1 18 109 19 2 1 1 96
0 0 138592 17932 126272 214244 0 0 0 0 105 46 0 1 0 99
0 0 138592 17932 126272 214244 0 0 0 0 198 62 40 14 0 45
0 0 138592 17932 126272 214244 0 0 0 0 117 49 0 0 0 100
0 0 138592 17924 126272 214244 0 0 0 176 220 938 3 4 13 80
0 0 138592 17924 126272 214244 0 0 0 0 358 1522 8 17 0 75
1 0 138592 17924 126272 214244 0 0 0 0 368 1447 4 24 0 72
0 0 138592 17924 126272 214244 0 0 0 0 352 1277 9 12 0 79
# vmstat 1
procs memory swap io system cpu
r b swpd free buff cache si so bi bo in cs us sy wa id
2 0 145940 17752 118600 215592 0 1 1 18 109 19 2 1 1 96
2 0 145940 15856 118604 215652 0 0 0 468 789 108 86 14 0 0
3 0 146208 13884 118600 214640 0 360 0 360 498 71 91 9 0 0
2 0 146388 13764 118600 213788 0 340 0 340 672 41 87 13 0 0
2 0 147092 13788 118600 212452 0 740 0 1324 620 61 92 8 0 0
2 0 147360 13848 118600 211580 0 720 0 720 690 41 96 4 0 0
2 0 147912 13744 118192 210592 0 720 0 720 605 44 95 5 0 0
2 0 148452 13900 118192 209260 0 372 0 372 639 45 81 19 0 0
2 0 149132 13692 117824 208412 0 372 0 372 457 47 90 10 0 0


二 CPU篇

首先介绍一下Linux kernel中的调度器(scheduler),调度器负责调度系统中的两种资源,一是线程,二是中断。调度器给不同资源不同的优先级。从高到低为:

1.硬件中断(HardwareInterrupts--这些请求由硬件触发,比如磁盘已经完成了读写任务或是网卡受到了新的数据包。

2.软件中断(SoftwareInterrupts)--这里指的是维护内核运行的内核态软件中断。比如内核的时钟管理进程。

3.实时进程(Real timethreads)--实时进程比内核本身具备更高的优先级,它可以抢占内核的CPU时间片,在2.4内核是一个不可抢占的内核,它中不支持实时程序。

4.内核进程(Kernel threads--包括所以的内核程序。

5.用户进程(User threads--所有运行在用户态的进程。

 

关于CPU,有3个重要的概念:上下文切换(context switchs),运行队列(Run queue)和使用率(utilization)。

上下文切换:

     目前流行的CPU在同一时间内只能运行一个线程,超线程的处理器可以在同一时间运行多个线程(包括多核CPU),Linux内核会把多核的处理器当作多个单独的CPU来识别。

      一个标准的Linux内核何以支持运行5050000个进程运行,对于普通的CPU,内核会调度和执行这些进程。每个进程都会分到CPU的时间片来运行,当一个进程用完时间片或者被更高优先级的进程抢占后,它会备份到CPU的运行队列中,同时其他进程在CPU上运行。这个进程切换的过程被称作上下文切换。过多的上下文切换会造成系统很大的开销。

 

运行队列

      每个CPU都会维持一个运行队列,理想情况下,调度器会不断让队列中的进程运行。进程不是处在sleep状态就是runable状态。如果CPU过载,就会出现调度器跟不上系统的要求,导致可运行的进程会填满队列。队列愈大,程序执行时间就愈长。“load”用来表示运行队列,用top命令我们可以看到CPU一分钟,5分钟和15分钟内的运行队列的大小。这个值越大表明系统负荷越大。

 

CPU使用率:

      CPU使用率可分为一下几个部分

      UserTime—执行用户进程的时间百分比;

      SystemTime—执行内核进程和中断的时间百分比;

      WaitIO—因为IO等待而使CPU处于idle状态的时间百分比;

      Idle—CPU处于Idle状态的时间百分比。

 

关于时间片和动态优先级:

时间片对于CPU来说是很关键的参数,如果时间片太长,就会使系统的交互性能变差,用户感觉不到并行。如果太短,又会造成系统频繁的上下文切换,使性能下降。对于IOBound的系统来讲并不需要太长的时间片,因为系统主要是IO操作;而对于CPUBound的系统来说需要长的时间片以保持cache的有效性。

每一个进程启动的时候系统都会给出一个默认的优先级,但在运行过程中,系统会根据进程的运行状况不断调整优先级,内核会升高或降低进程的优先级(每次增加或降低5),判断标准是根据进程处于sleep状态的时间。IOBound进程大部分时间在sleep状态,所以内核会调高它的优先级,CPUBound进程会被内核惩罚降低优先级。因此,如果一个系统上即运行IOBound进程,又运行CPUBound进程,我们会发现,IOBound进程的性能不会下降,而CPUBound进程性能会不断下降。

我们运行一个CPUBound的程序:cpu-hog。用ps命令可以看出它的优先级在不断下降。

term1#./cpu-hog

term2# while :;do ps -eo pid,ni,pri,pcpu,comm | egrep

‘hog|PRI‘;sleep 1; done

PID NI PRI %CPUCOMMAND

22855 0 20 84.5cpu-hog

PID NI PRI %CPUCOMMAND

22855 0 18 89.6cpu-hog

PID NI PRI %CPUCOMMAND

22855 0 15 92.2cpu-hog

PID NI PRI %CPUCOMMAND

22855 0 15 93.8cpu-hog

   我们运行find命令,是一个IO Bound的程序,可以观察到它的优先级不断提高。

term1# find/

term2# while :;do ps -eo pid,ni,pri,pcpu,comm | egrep

‘find|PRI‘;sleep 1; done

PID NI PRI %CPUCOMMAND

23101 0 20 0.0find

PID NI PRI %CPUCOMMAND

23101 0 21 4.0find

PID NI PRI %CPUCOMMAND

23101 0 23 3.5find

PID NI PRI %CPUCOMMAND

23101 0 23 4.3find

PID NI PRI %CPUCOMMAND

23101 0 23 4.2find

PID NI PRI %CPUCOMMAND

23101 0 23 4.4find

      如果同时运行2个程序就可看出明显的变化

#while :; do ps -eopid,ni,pri,pcpu,comm | egrep‘find|hog‘;

sleep 1;done

23675 0 20 70.9cpu-hog

23676 0 20 5.6find

23675 0 20 69.9cpu-hog

23676 0 21 5.6find

23675 0 20 70.6cpu-hog

23676 0 23 5.8find

23675 0 19 71.2cpu-hog

23676 0 23 6.0find

23675 0 19 71.8cpu-hog

23676 0 23 6.1find

23675 0 18 72.8cpu-hog

23676 0 23 6.2find

23675 0 16 73.2cpu-hog

23676 0 23 6.6find

23675 0 14 73.9cpu-hog

 

三内存篇

       我们首先了解虚拟内存和物理内存:虚拟内存就是采用硬盘来对物理内存进行扩展,将暂时不用的内存页写到硬盘上而腾出更多的物理内存让有需要的进程来用。当这些内存页需pi要用的时候在从硬盘读回内存。这一切对于用户来说是透明的。通常在Linux系统说,虚拟内存就是swap分区。在X86系统上虚拟内存被分为大小为4K的页。

       Linux性能监控每一个进程启动时都会向系统申请虚拟内存(VSZ),内核同意或者拒就请求。当程序真正用到内存时,系统就它映射到物理内存。RSS表示程序所占的物理内存的大小。用ps命令我们可以看到进程占用的VSZ和RSS。

# ps –aux

USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND

daemon 2177 0.0 0.2 3352 648 ? Ss 23:03 0:00 /usr/sbin/atd

dbus 2196 0.0 0.5 13180 1320 ? Ssl 23:03 0:00 dbus-daemon-1--sys

root 2210 0.0 0.4 2740 1044 ? Ss 23:03 0:00cups-config-daemon

root 2221 0.3 1.5 6108 4036 ? Ss 23:03 0:02 hald

root 2231 0.0 0.1 2464 408 tty1 Ss+ 23:03 0:00 /sbin/mingettytty1

内核会定期将内存中的数据同步到硬盘,这个过程叫做MemoryPaging。同时内核也要负责回收不用的内存,将他们分给其他需要的进程。PFRA算法(Page Frame reclaimalgorithm)负责回收空闲的内存。算法根据内存页的类型来决定要释放的内存页。有下列4种类型:

1. Unreclaimable – 锁定的,内核保留的页面;

2. Swappable – 匿名的内存页;

3. Syncable – 通过硬盘文件备份的内存页;

4. Discardable – 静态页和被丢弃的页。

除了第一种(Unreclaimable)之外其余的都可以被PFRA进行回收。与之相关的进程是kswapd。在kswapd中,有2个阀值,pages_hige和pages_low。当空闲内存页的数量低于pages_low的时候,kswapd进程就会扫描内存并且每次释放出32个free pages,直到free page的数量到达pages_high。具体kswapd是如何回收内存的呢?有如下原则:

1. 如果页未经更改就将该页放入空闲队列;

2. 如果页已经更改并且是可备份回文件系统的,就理解将内存页的内容写回磁盘;

3. 如果页已经更改但是没有任何磁盘上的备份,就将其写入swap分区。

# ps -ef | grep kswapd

root 30 1 0 23:01 ? 00:00:00 [kswapd0]

Linux性能监控在回收内存过程中还有两个重要的方法,一是LMR(Low on memoryreclaiming),另一个是OMK(Out of MemoryKiller)。当分配内存失败的时候LMR将会其作用,失败的原因是kswapd不能提供足够的空闲内存,这个时候LMR会每次释放1024个垃圾页知道内存分配成功。当LMR不能快速释放内存的时候,OMK就开始其作用,OMK会采用一个选择算法来决定杀死某些进程。当选定进程时,就会发送信号SIGKILL,这就会使内存立即被释放。OMK选择进程的方法如下:

1. 进程占用大量的内存;

2. 进程只会损失少量工作;

3. 进程具有低的静态优先级;

4. 进程不属于root用户。

Linux性能监控进程管理中另一个程序pdflush用于将内存中的内容和文件系统进行同步,比如说,当一个文件在内存中进行修改,pdflush负责将它写回硬盘。

# ps -ef | grep pdflush

root 28 3 0 23:01 ? 00:00:00 [pdflush]

root 29 3 0 23:01 ? 00:00:00 [pdflush]

每当内存中的垃圾页(dirtypage)超过10%的时候,pdflush就会将这些页面备份回硬盘。这个比率是可以调节的,通过参数vm.dirty_background_ratio。

# sysctl -n vm.dirty_background_ratio

Pdflush同PFRA是独立运行的,当内核调用LMR时,LMR就触发pdflush将垃圾页写回硬盘

四 IO篇

关于Linux性能监控相信大家已经小有了解,对于IO篇,让我们先分析一些具体的情况,在这些情况下I/O会成为系统的瓶颈。我们会用到工具topvmstatiostatsar等。每一个工具的输出都从不同的方面反映除系统的性能情况。

Linux性能监控情况1:同一时间进行大量的I/O操作

在这种情况时我们会发现CPUwa时间百分比会上升,证明系统的idle时间大部分都是在等待I/O操作。
# vmstat 1
procs -----memory----- ---swap---io---- --system--cpu----
r b swpd free buff cache si so bi bo in cs us sy id wa
3 2 0 55452 9236 1739020 0 0 9352 0 2580 8771 20 24 0 57
2 3 0 53888 9232 1740836 0 0 14860 0 2642 8954 23 25 0 52
2 2 0 51856 9212 1742928 0 0 12688 0 2636 8487 23 25 052

从这个输出我们可以看到CPU50%的时间都在等待I/O操作,我们还可以看到系统的bi值很大,证明系统有大量的I/O请求将磁盘内容读入内存。

没有很好的工具能看到到底是哪个进程在进行I/O读写。但我们可以通过top命令的输出来猜测
# top -d 1
top - 19:45:07 up 1:40, 3 users, load average: 6.36, 5.87,4.40
Tasks: 119 total, 3 running, 116 sleeping, 0 stopped, 0zombie
Cpu(s): 5.9% us, 87.1% sy, 0.0% ni, 0.0% id, 5.9% wa, 1.0% hi, 0.0%si
Mem: 2075672k total, 2022668k used, 53004k free, 7156kbuffers
Swap: 2031608k total, 132k used, 2031476k free, 1709372kcached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ nFLT COMMAND
3069 root 5 -10 450m 303m 280m S 61.5 15.0 10:56.68 4562vmware-vmx
3016 root 5 -10 447m 300m 280m S 21.8 14.8 12:22.83 3978vmware-vmx
3494 root 5 -10 402m 255m 251m S 3.0 12.6 1:08.65 3829vmware-vmx
3624 root 5 -10 401m 256m 251m S 1.0 12.6 0:29.92 3747vmware-vmx

top的输出通过faults进行排序。我们可以看到vmware产生最多的page faults。也就是说它进行了大量的IO操作。

Linux性能监控情况2:管道太小

任何I/O操作都需要一定的时间,而且这些时间对于硬盘来说是确定的,它包含磁盘旋转的延时RDrotation delay)和磁头搜索时间DSdisk seek)。RD由磁盘转速(RPM)决定。RD是磁盘旋转一周所需时间的一半。如RPM10000.
RPS=RPM/60=166
1/166=0.0006=6ms
 磁盘旋转一周要6毫秒
RD=6ms/2=3ms

磁盘平均搜索时间是3ms,数据传输的平均延时是2ms,这样一次I/O操作的平均时间是:
3ms+3ms+2ms=8ms
IOPS=1000/8=125
 这块磁盘的每秒IO数(IOPS)为125。所以对于10000RPM的磁盘来说它所能承受的IO操作在IOPS120150之间。如果系统的I/O请求超过这个值,就会使磁盘成为系统的瓶颈。

对与系统而言有两种不同种类的I/O压力,连续I/O和随机I/O

连续I/O常常出现在企业级数据库这样的应用中,需要连续的读取大量数据。这种系统的性能依靠它读取和移动数据的大小和快慢。我们用iostat来监控,会发现rKB/s,wKB/s会很高。
Device: rrqm/s wrqm/s r/s w/s rsec/s wsec/s rkB/swkB/s avgrq-sz avgqu-sz await svctm %util
/dev/sda 0.00 12891.43 0.00 105.71 0.00 106080.00 0.00 53040.001003.46 1099.43 3442.43 26.49 280.00

从输出我们看到w/s=105,wKB/s=53040.所以53040/105=505KB perI/O.

对于随机I/O的系统来说性能的关注点不在搜传输数据的大小和速度,而是在磁盘的IOPS。这类系统的I/O请求比较小但是数量很大,如Web服务器和Mail服务器。他们的性能主要依赖每秒钟可处理的请求数:
# iostat -x 1
avg-cpu: %user %nice %sys %idle
2.04 0.00 97.96 0.00
Device: rrqm/s wrqm/s r/s w/s rsec/s wsec/s rkB/s wkB/s avgrq-szavgqu-sz await svctm %util
/dev/sda 0.00 633.67 3.06 102.31 24.49 5281.63 12.24 2640.82 288.8973.67 113.89 27.22 50.00

从输出我们看到w/s=102,wKB/s=2640.所以2640/102=23KB perI/O.因此对于连续I/O系统来说我们要关注系统读取大量数据的能力即KB per request.对于随机I/O系统我们注重IOPS

 

五 Network篇

网络中最常见的错误就是冲突,由于网络中目前基本采用交换机环境,因此冲突问题已被消除。但是当网络流量不断增大的时候,就会出现丢包,网卡过载等情况。在网络流量很大的时候我们用sar命令来给出网络中可能的错误:

# sar -n FULL 5 100

Linux 2.6.9-55.ELsmp (sapulpa)06/23/2007

11:44:32 AM IFACE rxpck/s txpck/srxbyt/s txbyt/s rxcmp/s txcmp/s rxmcst/s

11:44:37 AM lo 6.00 6.00 424.40 424.400.00 0.00 0.00

11:44:37 AM eth0 0.00 0.00 0.00 0.000.00 0.00 0.00

11:44:37 AM sit0 0.00 0.00 0.00 0.000.00 0.00 0.00

11:44:32 AM IFACE rxerr/s txerr/scoll/s rxdrop/s txdrop/s txcarr/s rxfram/s rxfifo/s txfifo/s

11:44:37 AM lo 0.00 0.00 0.00 0.00 0.000.00 0.00 0.00 0.00

11:44:37 AM eth0 0.00 0.00 0.00 0.000.00 0.00 0.00 0.00 0.00

11:44:37 AM sit0 0.00 0.00 0.00 0.000.00 0.00 0.00 0.00 0.00

11:44:32 AM totsck tcpsck udpsck rawsckip-frag

11:44:37 AM 297 79 8 0 0

  rxerr/s是接受错误率;txerr/s是发送错误率;coll/s冲突率;rxdrop/s接受帧丢失率;txdrop/s发送帧丢失率;txcarr/s载波错误率;rxfram/s帧排列错误;rxfifo/s接受FIFO错误;txfifo/s发送FIFO错误。从上面输出看出各种错误为零,证明网络工作良好。

  总的来说监视网络性能,我们有遵循一下几点:

1. 检查所有网络接口确保他们都运行在正确的速率;

2. 检查每块网卡的吞吐量确保没有造成过载;

3. 检查流量的类型确保正确的数据流在传送。