日常的工做中,在衡量服务器的性能时,常常会涉及到几个指标,load、cpu、mem、qps、rt等。每一个指标都有其独特的意义,不少时候在线上出现问题时,每每会伴随着某些指标的异常。大部分状况下,在问题发生以前,某些指标就会提早有异常显示。java
对于这些指标的理解和查看、异常解决等,是程序员们重要的必备技能。本文,主要来介绍一下一个比较重要的指标——机器负载(Load),主要涉及负载的定义、查看负载方式、负载飙高排查思路等。linux
负载(load)是linux机器的一个重要指标,直观了反应了机器当前的状态。程序员
来看下负载的定义是怎样的:shell
In UNIX computing, the system load is a measure of the amount of computational work that a computer system performs. The load average represents the average system load over a period of time. It conventionally appears in the form of three numbers which represent the system load during the last one-, five-, and fifteen-minute periods.(wikipedia)数据库
简单解释一下:在UNIX系统中,系统负载是对当前CPU工做量的度量,被定义为特定时间间隔内运行队列中的平均线程数。load average 表示机器一段时间内的平均load。这个值越低越好。负载太高会致使机器没法处理其余请求及操做,甚至致使死机。api
Linux的负载高,主要是因为CPU使用、内存使用、IO消耗三部分构成。任意一项使用过多,都将致使服务器负载的急剧攀升。安全
/proc/loadavg
The first three fields in this file are load average figures giving the number of jobs in the run queue (state
R) or waiting for disk I/O (state D) averaged over 1, 5, and 15 minutes. They are the same as the load average
numbers given by uptime(1) and other programs. The fourth field consists of two numbers separated by a slash
(/). The first of these is the number of currently executing kernel scheduling entities (processes, threads);
this will be less than or equal to the number of CPUs. The value after the slash is the number of kernel
scheduling entities that currently exist on the system. The fifth field is the PID of the process that was most
recently created on the system.
在Linux机器上,有多个命令均可以查看机器的负载信息。其中包括uptime
、top
、w
等。服务器
uptime
命令uptime
命令可以打印系统总共运行了多长时间和系统的平均负载。uptime命令能够显示的信息显示依次为:如今时间、系统已经运行了多长时间、目前有多少登录用户、系统在过去的1分钟、5分钟和15分钟内的平均负载。app
➜ ~ uptime
13:29 up 23:41, 3 users, load averages: 1.74 1.87 1.97
复制代码
这行信息的后半部分,显示"load average",它的意思是"系统的平均负荷",里面有三个数字,咱们能够从中判断系统负荷是大仍是小。less
1.74 1.87 1.97
这三个数字的意思分别是1分钟、5分钟、15分钟内系统的平均负荷。咱们通常表示为load一、load五、load15。
w
命令w命令的主要功能实际上是显示目前登入系统的用户信息。可是与who不一样的是,w命令功能更增强大,w命令还能够显示:当前时间,系统启动到如今的时间,登陆用户的数目,系统在最近1分钟、5分钟和15分钟的平均负载。而后是每一个用户的各项数据,项目显示顺序以下:登陆账号、终端名称、远 程主机名、登陆时间、空闲时间、JCPU、PCPU、当前正在运行进程的命令行。
➜ ~ w
14:08 up 23:41, 3 users, load averages: 1.74 1.87 1.97
USER TTY FROM LOGIN@ IDLE WHAT
hollis console - 六14 23:40 -
hollis s000 - 六14 20:24 -zsh
hollis s001 - 六15 - w
复制代码
从上面的w
命令的结果能够看到,当前系统时间是14:08,系统启动到如今经历了23小时41分钟,共有3个用户登陆。系统在近1分钟、5分钟和15分钟的平均负载分别是1.74 1.87 1.97
。这和uptime
获得的结果相同。 下面还打印了一些登陆的用户的各项数据,不详细介绍了。
top
命令top命令是Linux下经常使用的性能分析工具,可以实时显示系统中各个进程的资源占用情况,相似于Windows的任务管理器。
➜ ~ top
Processes: 244 total, 3 running, 9 stuck, 232 sleeping, 1484 threads 14:16:01
Load Avg: 1.74, 1.87, 1.97 CPU usage: 8.0% user, 6.79% sys, 85.19% idle SharedLibs: 116M resident, 16M data, 14M linkedit. MemRegions: 66523 total, 2152M resident, 50M private, 930M shared.
PhysMem: 7819M used (1692M wired), 370M unused. VM: 682G vsize, 533M framework vsize, 6402060(0) swapins, 7234356(0) swapouts. Networks: packets: 383006/251M in, 334448/60M out.
Disks: 1057821/38G read, 350852/40G written.
PID COMMAND %CPU TIME #TH #WQ #PORT MEM PURG CMPRS PGRP PPID STATE BOOSTS %CPU_ME %CPU_OTHRS UID FAULTS COW MSGSENT MSGRECV SYSBSD SYSMACH CSW
30845 top 3.0 00:00.49 1/1 0 21 3632K 0B 0B 30845 1394 running *0[1] 0.00000 0.00000 0 3283+ 112 203556+ 101770+ 8212+ 119901+ 823+
30842 Google Chrom 0.0 00:47.39 17 0 155 130M 0B 0B 1146 1146 sleeping *0[1] 0.00000 0.00000 501 173746 2697 117678 37821 364228 444830 310043
复制代码
上面的输出结果中,Load Avg: 1.74, 1.87, 1.97显示的就是负载信息。
对于机器的Load到底多少算正常的问题,一直都是颇有争议的,不一样人有着不一样的理解。对于单个CPU,有人认为若是Load超过0.7就算是超出正常范围了。也有人认为只要不超过1都没问题。也有人认为,单个CPU的负载在2如下均可以接受。
为何会有这么多不一样的理解呢,是由于不一样的机器除了CPU影响以外还有其余因素的影响,运行的程序、机器内存、甚至是机房温度等都有可能有区别。
好比,有些机器用于定时执行大量的跑批任务,这个时间段内,Load可能会飙的比较高。而其余时间可能会比较低。那么这段飙高时间咱们要不要去排查问题呢?
个人建议是,最好根据本身机器的实际状况,创建一个指标的基线(如近一个月的平均值),只要平常的load在基线上下范围内不太大均可以接收,若是差距太多可能就要人为介入检查了。
可是,总要有个建议的阈值吧,关于这个值。阮一峰在本身的博客中有过如下建议:
当系统负荷持续大于0.7,你必须开始调查了,问题出在哪里,防止状况恶化。
当系统负荷持续大于1.0,你必须动手寻找解决办法,把这个值降下来。
当系统负荷达到5.0,就代表你的系统有很严重的问题,长时间没有响应,或者接近死机了。你不该该让系统达到这个值。
以上指标都是基于单CPU的,可是如今不少电脑都是多核的。因此,对通常的系统来讲,是根据cpu数量去判断系统是否已通过载(Over Load)的。若是咱们认为0.7算是单核机器负载的安全线的话,那么四核机器的负载最好保持在3(4*0.7 = 2.8)如下。
还有一点须要提一下,在Load Avg的指标中,有三个值,1分钟系统负荷、5分钟系统负荷,15分钟系统负荷。咱们在排查问题的时候也是能够参考这三个值的。
通常状况下,1分钟系统负荷表示最近的暂时现象。15分钟系统负荷表示是持续现象,并不是暂时问题。若是load15较高,而load1较低,能够认为状况有所好转。反之,状况可能在恶化。
致使负载高的缘由可能很复杂,有多是硬件问题也多是软件问题。
若是是硬件问题,那么说明机器性能确实就不行了,那么解决起来很简单,直接换机器就能够了。
前面咱们提过,CPU使用、内存使用、IO消耗均可能致使负载高。若是是软件问题,有可能因为Java中的某些线程被长时间占用、大量内存持续占用等致使。建议从如下几个方面排查代码问题:
一、是否有内存泄露致使频繁GC 二、是否有死锁发生 三、是否有大字段的读写 四、会不会是数据库操做致使的,排查SQL语句问题。五、死循环
这里还有个建议,若是发现线上机器Load飙高,能够考虑先把堆栈内存dump下来后,进行重启,暂时解决问题,而后再考虑回滚和排查问题。
一、使用uptime查看当前load,发现load飙高。
➜ ~ uptime
13:29 up 23:41, 3 users, load averages: 10 10 10
复制代码
二、使用top命令,查看占用CPU较高的进程ID。
➜ ~ top
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1893 admin 20 0 7127m 2.6g 38m S 181.7 32.6 10:20.26 java
复制代码
发现PID为1893的进程占用CPU 181%。并且是一个Java进程,基本判定是软件问题。
三、使用 top
命令,查看具体是哪一个线程占用率较高
➜ ~ top -Hp 1893
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
4519 admin 20 0 7127m 2.6g 38m R 18.6 32.6 0:40.11 java
复制代码
四、使用printf
命令查看这个线程的16进制
➜ ~ printf %x 4519
11a7
复制代码
五、使用jstack
命令查看当前线程正在执行的方法。(Java命令学习系列(二)——Jstack)
➜ ~ jstack 1893 |grep -A 200 11a7
"thread-5" #500 daemon prio=10 os_prio=0 tid=0x00007f632314a800 nid=0x11a2 runnable [0x000000005442a000]
java.lang.Thread.State: RUNNABLE
at sun.misc.URLClassPath$Loader.findResource(URLClassPath.java:684)
at sun.misc.URLClassPath.findResource(URLClassPath.java:188)
at java.net.URLClassLoader$2.run(URLClassLoader.java:569)
at java.net.URLClassLoader$2.run(URLClassLoader.java:567)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findResource(URLClassLoader.java:566)
at org.hibernate.validator.internal.xml.ValidationXmlParser.getInputStreamForPath(ValidationXmlParser.java:248)
at com.hollis.test.util.BeanValidator.validate(BeanValidator.java:30)
复制代码
从上面的线程的栈日志中,能够发现,当前占用CPU较高的线程正在执行我代码的com.hollis.test.util.BeanValidator.validate(BeanValidator.java:30)类。那么就能够去排查这个类是否用法有问题了。
做者:Hollis_公众号Hollis连接:https://juejin.im/post/5b0262edf265da0b9b079fa7来源:掘金著做权归做者全部。商业转载请联系做者得到受权,非商业转载请注明出处。