ECS服务器以最优的状态运行,ECS硬件配置、系统问题、系统架构、网络、软件等问题都会影响到系统的性能好坏,如何定位性能问题出在哪个方面,如何解决性能问题,是ECS性能优化的一大难题。本ECS篇从这些方面,重点讲述优化CPU、内存、IO的性能问题的方法,并且提供ECS典型优化案例。
linux内核会将多核的处理器当做多个单独的CPU来识别,例如,两个4核的CPU会被当成8个单个CPU,从性能角度讲,两个4核的CPU整体性能要比8个单核CPU低25%-30%。
可能出现CPU瓶颈的数据库服务器、动态web服务器等。
1.硬件配置低,难以满足应用正常运行所需的CPU资源
2. 数据库不要安装在ECS上,数据库程序有问题,会导致CPU高,建议将数据库迁移到RDS,数据库优化可以参考性能优化-RDS篇。
3.应用程序的优化也是CPU性能优化核心,如果一个应用程序存在BUG,那么即使所有其他方面都达到了最优状态,整个应用系统还是性能低下,CPU还是飘高,因此对应用程序的优化对性能优化是格外重要
1.通过系统命令查看CPU信息
Linux常用命令:PS、TOP来查看CPU使用率、进程等等信息,
windows系统使用系统管理器查看CPU使用率、进程等等信息。性能计数器监控一定时间范围内CPU使用率。
当CPU使用率高,发生的时间很难控制,编辑脚本将监控数据输出到log文件里。案例脚本见文档最后附件脚本
A. uptime命令
uptime是监控系统性能最常用的一个命令,主要用来统计系统当前的运行状况。输出的信息依次为:系统现在的时间、系统从上次开机到现在运行了多少时间,系统目前多少登录用户,系统在1分钟内、5分钟内、15分钟内的平均负载。
JST#uptime
13:05:56 up 353 days, 21:08, 7 users, load average: 1.01, 0.85, 0.43
load average3个值的大小一般不能大于系统CPU的个数。
例如:本输出中系统有8个cpu,如果load average的3个值长期大约8时,说明CPU很繁忙,负载很高,可能会影响系统性能;如果偶尔大于8,一般不会影响系统性能。
top提供了实时对系统处理器状态的监控,能够实时显示系统中各个进程的资源占用状况。可以按照CPU的使用、内存的使用、和执行时间对系统任务进程排序,同时可以通过交互式命令进行设定显示。类似于windows的任务管理器。
top选项很多,常用的有
-d 指定每两次屏幕信息刷新之间的时间间隔
-i 不显示闲置或者僵死的进程
-c 显示进程的整个命令路径,而不是只显示命令名称
-s 使top在安全模式下运行,此时top的交互式指令被取消,
-b分屏显示输出信息,结合-n选项可以将屏幕信息输出到文档
-n top输出信息更新次数,完成后将退出top命令
下面看个典型例子
JST#top
top - 19:59:47 up 27 days, 4:55, 6 users, load average: 1.06, 1.04, 1.06
Tasks: 123 total, 2 running, 119 sleeping, 1 stopped, 1 zombie
Cpu(s): 0.1% us, 2.5% sy, 10.2% ni, 87.2% id, 0.0% wa, 0.0% hi, 0.0% si
Mem: 47811272k total, 28204544k used, 19606728k free, 41044k buffers
Swap: 0k total, 0k used, 0k free, 4276844k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
23699 user 35 10 70932 17m 4992 R 99.9 0.0 1842:59 sh
63 root 15 0 0 0 0 S 0.0 0.0 54:00.46 kswapd0
18661 root 16 0 98408 7344 3136 S 0.0 0.0 43:54.33 naming-agent
12944 root 16 0 18020 2844 2016 S 0.0 0.0 4:54.12 executor
24971 root 16 0 241m 184m 3060 S 0.0 0.4 3:54.96 webfoot-agent
1298 root 16 0 5792 844 612 S 0.0 0.0 3:35.97 syslogd
62 root 15 0 0 0 0 S 0.0 0.0 1:42.33 pdflush
61 root 15 0 0 0 0 S 0.0 0.0 1:37.29 pdflush
top输出分为统计信息区和进程信息区
1)统计信息区
第一行为任务队列信息
19:59:47 表示当前系统时间
up 27days 4:55 表示系统已经启动了27天4小时55分
6users表示当前登录系统的用户数
load average表示系统平均负载,3个数值分布式1分钟,5分钟和15分钟前到现在的系统平均负载值
第二、三行为进程和CPU信息,
tasks表示进程的总数
2 running 表示正在运行的进程数
119sleeping 处于休眠的进程数
1 stopped 停止的进程数
1 zombie 僵死的进程数
Cpu(s); 0.1% us用户进程占用CPU百分比
2.5%sy 系统进程占用CPU百分比
10.2%ni 用户进程空间内改变过优先级的进程占用CPU
87.2%id 空闲CPU
0.0%wa 等待输入输出的进程占用CPU百分比
2)进程信息区
显示了每个进程的运行状态,
PID进程的id
USER进程所有者的用户名
PR进程优先级
NI:nice值,负值表示高优先级,正值表示低优先级
VIRT进程使用的虚拟内存总量,单位为KB,VIRT=SWAP+RES
RES 进程使用的未被交换出的物理内存大小,单位为KB. RES=CODE+DATA
SHR 共享内存大小,单位为KB
S进程状态,D表示不可中断的睡眠状态,R表示运行状态,S表示睡眠状态,T表示跟踪/停止,Z表示僵尸进程
%CPU 上次更新到现在的CPU时间占用百分比
%MEM进程占用的物理内存百分比
TIME+ 进程使用的CPU时间总计,单位为1/100秒
COMMAND 正在运行进程的命令名或命令路径
3.CPU系统性分析标准和优化原则
好: user%+sys%<50%
坏: user%+sys%=75%
糟糕: user%+sys%>=90%
一个十万火急的CASE,客户抱怨ECS升级后系统会变慢和CPU使用率相当高,客户脾气很大,声称不尽快解决这个问题就退货,排查解决的思路如下:
1.首先用top命令查看哪个进程占用CPU高
gateway网关进程13094占用CPU高达891%,这个数值是进程内各个线程占用CPU的累加值。
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
13009 root 15 0 315m 10m 7308 S 891% 2.2 1:49.01 gateway
20642 root 17 0 17784 4138 2220 S 0.5 0.8 2:39.96 microdasys
1679 root 18 0 10984 1856 1556 R 0.3 0.4 0:22.21 sshd
22563 root 18 0 2424 1060 800 R 0.3 0.2 0:00.03 top
1 root 18 0 2156 492 460 S 0.0 0.1 0:01.59 init
2.用top -H -p pid命令查看进程内各个线程占用的CPU百分比
#top -H -p 13009
top中可以看到有107个线程,但是下面9个线程占用CPU很高,下面以线程13086为主,分析其为何high CPU
PID USER PR NI VIRT RES SHR S %CPU MEM TIME+ COMMAND
13086 root 25 0 922m 913m 538m R 101 10.0 21:35.46 gateway
13087 root 25 0 922m 913m 538m R 101 10.0 10:50.22 gateway
13081 root 25 0 922m 913m 538m S 99 10.0 8:57.36 gateway
13082 root 25 0 922m 913m 538m R 99 10.0 11:51.92 gateway
13089 root 25 0 922m 913m 538m R 99 10.0 21:21.77 gateway
13092 root 25 0 922m 913m 538m R 99 10.0 19:55.47 gateway
13094 root 25 0 922m 913m 538m R 99 10.0 21:02.21 gateway
13083 root 25 0 922m 913m 538m R 97 10.0 21:32.39 gateway
13088 root 25 0 922m 913m 538m R 97 10.0 11:23.12 gateway
3.使用gstack命令查看进程中各线程的函数调用栈
#gstack 13094 > gstack.log
在gstack.log中查找线程ID13086,由于函数栈会暴露函数细节,因此只显示了两个函数桢,线程ID13086对应线程号是37
Thread 37 (Thread 0x4696ab90 (LWP 13086)):
#0 0x40000410 in __kernel_vsyscall ()
#1 0x40241f33 in poll () from /lib/i686/nosegneg/libc.so.6
4.使用gcore命令转存进程映像及内存上下文
#gcore 13094
该命令生成core文件core.13094
5。用strace命令查看系统调用和花费的时间
#strace -T -r -c -p 13094
-c参数显示统计信息,去掉此参数可以查看每个系统调用话费的时间及返回值。
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------------------
99.99 22.683879 3385 6702 poll
0.00 0.001132 0 6702 gettimeofday
0.00 0.000127 1 208 208 accept
0.00 0.000022 22 1 read
0.00 0.000000 0 1 write
0.00 0.000000 0 1 close
0.00 0.000000 0 13 time
0.00 0.000000 0 2 stat64
0.00 0.000000 0 4 clock_gettime
0.00 0.000000 0 7 send
0.00 0.000000 0 10 10 recvfrom
------ ----------- ----------- --------- --------- ------------------------------
100.00 22.685160 13652 218 total
6.用gdb调试core文件,并线程切换到37号线程
gcore和实际的core dump时产生的core文件几乎一样,只是不能用gdb进行某些动态调试
(gdb) gdb gateway core.13094
(gdb) thread 37
[Switching to thread 37 (Thread 0x4696ab90 (LWP 13086))]#0 0x40000410 in __kernel_vsyscall ()
(gdb) where
#0 0x40000410 in __kernel_vsyscall ()
#1 0x40241f33 in poll () from /lib/i686/nosegneg/libc.so.6
可以根据详细的函数栈进行gdb调试,打印一些变量值,并结合源代码分析为何会poll调用占用很高的CPU。
因为代码涉及到客户的数据安全,故不在此做详细分析,需要明白的是分析的流程和使用的命令。
优化内存的管理,提高内存的使用效率,尽可能地提高运行速度,。下面介绍在Windows \linux中,影响的因素,提高内存的使用效率和优化内存的方法
内存太小,系统进程将被阻塞,应用也将变得缓慢,甚至失去响应;内存太大,导致资源浪费。虚拟内存可以缓解物理内存的不足,但是虚拟内存的过多占用会导致应用程序的性能明显下降。虚拟内存消耗更多,意味着服务器的空闲内存已经不够。
在一个32位处理器的windows、linux系统中超过4GB的物理内存都将被浪费,因此要使用更大的内存,建议选择64位的操作系统,同时开启linux的大内存内核支持。由于处理器寻址范围的限制,在32位linux操作系统上,应用程序单个进程最大只能使用2GB的内存。
A.硬件配置低,难以满足应用正常运行所需的内存资源
B. 系统配置
C.应用程序设计不好
好:SwapIn(si) = 0 SwapOut(so) = 0
坏:Per CPU with 10page/s
糟糕:more swap In & swap out
A.通过应用管家监控ECS服务器的内存使用情况:
B.Top-Linux进程监控
Linux下的Top命令是一个性能监控程序,许多系统管理员常常用它来监控Linux性能,在许多Linux或者类Unix操作系统里都有这个命令。Top命令用于按一定的顺序显示所有正在运行而且处于活动状态的实时进程,而且会定期更新显示结果。这条命令显示了CPU的使用率、内存使用率、交换内存使用大小、高速缓存使用大小、缓冲区使用大小,进程PID、所使用命令以及其他。它还可以显示正在运行进程的内存和CPU占用多的情况。对系统管理员来说,top命令式是一个非常有用的,它可用于监控系统并在需要的时候采取正确的处理动作。让我们看看实际中的top命令。
下面看个典型例子
JST#top
top - 19:59:47 up 27 days, 4:55, 6 users, load average: 1.06, 1.04, 1.06
Tasks: 123 total, 2 running, 119 sleeping, 1 stopped, 1 zombie
Cpu(s): 0.1% us, 2.5% sy, 10.2% ni, 87.2% id, 0.0% wa, 0.0% hi, 0.0% si
Mem: 47811272k total, 28204544k used, 19606728k free, 41044k buffers
Swap: 0k total, 0k used, 0k free, 4276844k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
23699 user 35 10 70932 17m 4992 R 99.9 0.0 1842:59 sh
63 root 15 0 0 0 0 S 0.0 0.0 54:00.46 kswapd0
18661 root 16 0 98408 7344 3136 S 0.0 0.0 43:54.33 naming-agent
12944 root 16 0 18020 2844 2016 S 0.0 0.0 4:54.12 executor
24971 root 16 0 241m 184m 3060 S 0.0 0.4 3:54.96 webfoot-agent
1298 root 16 0 5792 844 612 S 0.0 0.0 3:35.97 syslogd
62 root 15 0 0 0 0 S 0.0 0.0 1:42.33 pdflush
61 root 15 0 0 0 0 S 0.0 0.0 1:37.29 pdflush
top输出内存方面的信息,CPU在CPU优化部分描述
最后两行输出的是内存信息,
Mem total系统的物理内存大小
used 已经使用的物理内存大小
free 目前空余的内存大小
buffers 用作内核缓冲区的内存大小
Swap total交换分区的内存大小
used 已经使用的交换分区大小
free空闲的交换分区大小
cached 高速缓存的大小
C.VmStat内存统计
Linux的VmStat命令用于显示虚拟内存、内核线程、磁盘、系统进程、I/O 块、中断、CPU 活动 等的统计信息。缺省情况下,vmstat命令在 Linux 系统下不可用,需要安装一个包含了vmstat 程序的sysstat软件包。命令格式的常见用法是:
通常使用vmstat 5 5(表示在5秒时间内进行5次采样)命令测试。将得到一个数据汇总他能够反映真正的系统情况。
JST#vmstat 5 5
procs -----------memory---------- ---swap-- -----io---- --system-- ----cpu----
r b swpd free buff cache si so bi bo in cs us sy id wa
1 0 62792 3460 9116 88092 6 30 189 89 1061 569 17 28 54 2
0 0 62792 3400 9124 88092 0 00 14 884 434 4 14 81 0
0 0 62792 3400 9132 88092 0 00 14 877 424 4 15 81 0
1 0 62792 3400 9140 88092 0 00 14 868 418 6 20 74 0
1 0 62792 3400 9148 88092 0 00 15 847 400 9 25 67 0
A.在Windows中,驻留内存中的数据越多,就越要占用内存资源。一般考虑重新启动计算机。
B.Windows直接使用任务管理器查看,也可使用性能管理器添加内存计数器来动态监控。
一般方法查看到高内存的进程,判断是否是应用程序需要优化或出现死循环,结束相关僵尸进程。
改变页面文件的位置,更改虚拟内存,其目的主要是为了保持虚拟内存的连续性。
改变了页面文件的位置后,调整最大、最小页面文件,不要将设为等值
如果你发现系统的内存不多了,就要注意释放内存。释放内存最简单有效的方法,就是重新启动计算机。另外,就是关闭暂时不用的程序。特别是sleep、僵尸进程,从而将它所占用的大量的内存释放出来。
C.linux,可以通过dmidecode | grep -A16 “Memory Device$”命令来查看机器插了多少根内存条,以及每根内存条的具体型号,内存条的具体型号,对应用的运行性能也会有些影响,但一般来说不会有CPU那么明显,如java应用
linux要查看机器上内存的使用状况,可通过free -m来查看, free+buffers+cached,os为了提升运行性能,会利用一些内存来做cache,以提升诸如读写文件的速度等。
D.一般方法查看到高内存的进程,判断是否是应用程序需要优化或出现死循环,结束相关sleep和僵尸进程,释放内存。
E.编辑脚本将监控数据输出到log文件里。案例脚本见文档最后附件脚本
F.Linux内核的shmall和shmmax参数优化
SHMMAX= 配置了最大的内存segment的大小 ------>这个设置的比SGA_MAX_SIZE大比较好。
SHMMIN= 最小的内存segment的大小
SHMMNI= 整个系统的内存segment的总个数
SHMSEG= 每个进程可以使用的内存segment的最大个数
配置信号灯( semphore )的参数:
SEMMSL= 每个semphore set里面的semphore数量 -----> 这个设置大于你的process的个数吧,否则你不得不分多个semphore set,好像有process+n之说,我忘了n是几了。
SEMMNI= 整个系统的semphore set总数
SEMMNS=整个系统的semphore总数
shmall 是全部允许使用的共享内存大小,shmmax 是单个段允许使用的大小。这两个可以设置为内存的 90%。例如 16G 内存,16*1024*1024*1024*90% = 15461882265,shmall 的大小为 15461882265/4k(getconf PAGESIZE可得到) = 3774873。
修改 /etc/sysctl.conf
kernel.shmmax=15461882265
kernel.shmall=3774873
kernel.msgmax=65535
kernel.msgmnb=65535
执行 sudo sysctl -p
可以使用 ipcs -l 看结果。ipcs -u 可以看到实际使用的情况
IO性能对于一个系统的影响是至关重要的。一个系统经过多项优化以后,瓶颈往往落在数据库;而数据库经过多种优化以后,瓶颈最终会落到IO。而IO性能的发展,明显落后于CPU的发展。Memchached也好,NoSql也好,这些流行技术的背后都在直接或者间接地回避IO瓶颈,从而提高系统性能。传统的物理环境部署RAID、SAN等等提高IO能力。现在云上,底层已经做好了
A.硬件配置低,系统过于忙碌,硬件配置、网络等等满足不了目前业务对IO的要求
B.过多的死进程或僵尸进程
C.数据库安装在ECS上,应用程序存在bug等
D.系统消耗过多的交换内存或虚拟内存(见内存优化部分)
Iotop-监控Linux磁盘I/O
Iotop命令同样也非常类似于top命令和Htop程序,不过它具有监控并显示实时磁盘I/O和进程的统计功能。在查找具体进程和大量使用磁盘读写进程的时候,这个工具就非常有用。
JST#iotop
Windows机器通过任务管理器或性能计数器可查看系统IO的信息
A.Cache策略,充分利用cpu和内存的资源来缓解磁盘读写压力。
B.服务器前端部署SLB,分担服务器的读写压力
C.前端部署OCS,缓存数据,提高读写速率,减轻后端服务器IO压力
D.通过监控命令,查出高IO的进程,直接杀掉,或进行应用程序优化
E. 编辑脚本将监控数据输出到log文件里。案例脚本见文档最后附件脚本
好:iowait%<20%
坏:iowait%>=35%
糟糕:iowait%>=50%
linux下监控cpu、memo、io、swap性能数据的脚本,仅供参考
直接贴脚本:
1、cpu
#!/bin/bash
CurrentDate=`date -d today '+%Y%m%d'`
CurrentTime=`date -d today '+%Y%m%d%H%M'`
mytext="$CurrentTime\t`top -b -n 1 | grep Cpu\(s\)`"
echo -e $mytext >> /home/www/monitor/log/cpu$CurrentDate.log
2、memo
#!/bin/bash
CurrentDate=`date -d today '+%Y%m%d'`
CurrentTime=`date -d today '+%Y%m%d%H%M'`
mytext="$CurrentTime\t`top -b -n 1 | grep Mem:`"
echo -e $mytext >> /home/www/monitor/log/memo$CurrentDate.log
3、io
#!/bin/bash
CurrentDate=`date -d today '+%Y%m%d'`
CurrentTime=`date -d today '+%Y%m%d%H%M'`
mytext="$CurrentTime\t`iostat -p sda | grep -w sda`"
echo -e $mytext >> /home/www/monitor/log/io$CurrentDate.log
4、swap
#!/bin/bash
CurrentDate=`date -d today '+%Y%m%d'`
CurrentTime=`date -d today '+%Y%m%d%H%M'`
mytext="$CurrentTime\t`top -b -n 1 | grep Swap:`"
echo -e $mytext >> /home/www/monitor/log/swap$CurrentDate.log