日常的工做中,在衡量服務器的性能時,常常會涉及到幾個指標,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來源:掘金著做權歸做者全部。商業轉載請聯繫做者得到受權,非商業轉載請註明出處。