線上問題排查常用指令
記憶體瓶頸
free
free 是檢視記憶體使用情況,包括實體記憶體、交換記憶體 (swap) 和核心緩沖區記憶體。
free -h -s 3 表示每隔三秒輸出一次記憶體情況,指令如下
[1014154@cc69dd4c5-4tdb5 ~]$ free
total used free shared buff/cache available
Mem: 119623656 43052220 45611364 4313760 30960072 70574408
Swap: 0 0 0
[1014154@cc69dd4c5-4tdb5 ~]$ free -h -s 3
total used free shared buff/cache available
Mem: 114G 41G 43G 4.1G 29G 67G
Swap: 0B 0B 0B
total used free shared buff/cache available
Mem: 114G 41G 43G 4.1G 29G 67G
Swap: 0B 0B 0B
- Mem :是記憶體的使用情況。
- Swap :是交換空間的使用情況。
- total :系統總的可用實體記憶體和交換空間大小。
- used :已經被使用的實體記憶體和交換空間。
- free :還有多少實體記憶體和交換空間可用使用,是真正尚未被使用的實體記憶體數量。
- shared :被共享使用的實體記憶體大小。
- buff/cache :被 buffer(緩沖區) 和 cache(緩存) 使用的實體記憶體大小。
- available :還可以被應用程式使用的實體記憶體大小,它是從應用程式的角度看到的可用記憶體數量,available ≈ free + buffer + cache。
交換空間 (swap space)
swap space 是磁盤上的一塊區域,當系統實體記憶體吃緊時,Linux 會将記憶體中不常通路的資料儲存到 swap 上,這樣系統就有更多的實體記憶體為各個程序服務,而當系統需要通路 swap 上存儲的内容時,再将 swap 上的資料加載到記憶體中,這就是常說的換出和換入。交換空間可以在一定程度上緩解記憶體不足的情況,但是它需要讀寫磁盤資料,是以性能不是很高。
vmstat(推薦)
vmstat(VirtualMeomoryStatistics,虛拟記憶體統計)是 Linux 中監控記憶體的常用工具,可對作業系統的虛拟記憶體、程序、CPU 等的整體情況進行監視,推薦使用。
vmstat 5 3 表示每隔 5 秒統計一次,一共統計三次。
[1014154@cc69dd4c5-4tdb5 ~]$ vmstat 5 3
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
8 0 0 45453212 374768 30763728 0 0 14 99 1 1 11 10 78 0 1
10 0 0 45489232 374768 30763360 0 0 2 1275 95118 97908 13 11 75 0 1
6 0 0 45452908 374768 30765148 0 0 0 3996 89924 92073 12 10 78 0 1
procs
r:表示運作和等待 CPU 時間片的程序數(就是說多少個程序真的配置設定到 CPU),這個值如果長期大于系統 CPU 個數,說明 CPU 不足,需要增加 CPU。b:表示在等待資源的程序數,比如正在等待 I/O 或者記憶體交換等。
memory
swpd:表示切換到記憶體交換區的記憶體大小,即虛拟記憶體已使用的大小(機關 KB),如果大于 0,表示你的機器實體記憶體不足了,如果不是程式記憶體洩露的原因,那麼你該更新記憶體了或者把耗記憶體的任務遷移到其他機器。free:表示目前空閑的實體記憶體。buff:表示緩沖大小,一般對塊裝置的讀寫才需要緩沖 Cache:表示緩存大小,一般作為檔案系統進行緩沖,頻繁通路的檔案都會被緩存,如果 cache 值非常大說明緩存檔案比較多,如果此時 io 中的 bi 比較小,說明檔案系統效率比較好。
swap
si:表示資料由磁盤讀入記憶體;通俗的講就是每秒從磁盤讀入虛拟記憶體的大小,如果這個值大于 0,表示實體記憶體不夠用或者記憶體洩露了,要查找耗記憶體程序解決掉。so:表示由記憶體寫入磁盤,也就是由記憶體交換區進入記憶體的資料大小。
注意:一般情況下 si、so 的值都為 0,如果 si、so 的值長期不為 0,則說明系統記憶體不足,需要增加系統記憶體
io
bi:表示由塊裝置讀入資料的總量,即讀磁盤,機關 kb/s bo:表示寫到塊裝置資料的總量,即寫磁盤,機關 kb/s
注意:如果 bi+bo 的值過大,且 wa 值較大,則表示系統磁盤 IO 瓶頸。
system
in:表示某一時間間隔内觀測到的每秒裝置終端數。cs:表示每秒産生的上下文切換次數,這個值要越小越好,太大了,要考慮調低線程或者程序的數目。例如在 apache 和 nginx 這種 web 伺服器中,我們一般做性能測試時會進行幾千并發甚至幾萬并發的測試,選擇 web 伺服器的程序可以由程序或者線程的峰值一直下調,壓測,直到 cs 到一個比較小的值,這個程序和線程數就是比較合适的值了。系統調用也是,每次調用系統函數,我們的代碼就會進入核心空間,導緻上下文切換,這個是很耗資源,也要盡量避免頻繁調用系統函數。上下文切換次數過多表示你的 CPU 大部分浪費在上下文切換,導緻 CPU 幹正經事的時間少了,CPU 沒有充分利用,是不可取的。
注意:這兩個值越大,則由核心消耗的 CPU 就越多。
CPU
us:表示使用者程序消耗的 CPU 時間百分比,us 值越高,說明使用者程序消耗 CPU 時間越多,如果長期大于 50%,則需要考慮優化程式或者算法。sy:表示系統核心程序消耗的 CPU 時間百分比,一般來說 us+sy 應該小于 80%,如果大于 80%,說明可能存在 CPU 瓶頸。id:表示 CPU 處在空間狀态的時間百分比。wa:表示 IP 等待所占用的 CPU 時間百分比,wa 值越高,說明 I/O 等待越嚴重,根據經驗 wa 的參考值為 20%,如果超過 20%,說明 I/O 等待嚴重,引起 I/O 等待的原因可能是磁盤大量随機讀寫造成的,也可能是磁盤或者監控器的貸款瓶頸(主要是塊操作)造成的。
sar
sar 和 free 類似 sar -r 3 每隔三秒輸出一次記憶體資訊:
[root@localhost ~]# sar -r 3
Linux 3.10.0-1062.el7.x86_64 (localhost.localdomain) 2020年04月28日 _x86_64_ (2 CPU)
15時40分10秒 kbmemfree kbmemused %memused kbbuffers kbcached kbcommit %commit kbactive kbinact kbdirty
15時40分13秒 106800 1314960 92.49 2144 573248 4110864 116.82 563664 498888 36
15時40分16秒 106816 1314944 92.49 2144 573248 4110864 116.82 563668 498888 36
15時40分19秒 106816 1314944 92.49 2144 573248 4110864 116.82 563668 498888 36
CPU 瓶頸
檢視機器 cpu 核數
CPU總核數 = 實體CPU個數 * 每顆實體CPU的核數
總邏輯CPU數 = 實體CPU個數 * 每顆實體CPU的核數 * 超線程數
檢視 CPU 資訊(型号)
[1014154@cc69dd4c5-4tdb5 ~]$ cat /proc/cpuinfo | grep name | cut -f2 -d: | uniq -c
32 Intel(R) Xeon(R) CPU E5-2650 v4 @ 2.20GHz
檢視實體 CPU 個數
[1014154@cc69dd4c5-4tdb5 ~]$ cat /proc/cpuinfo| grep "physical id"| sort| uniq| wc -l
16
檢視每個實體 CPU 中 core 的個數 (即核數)
[1014154@cc69dd4c5-4tdb5 ~]$ cat /proc/cpuinfo| grep "cpu cores"| uniq
cpu cores : 2
檢視邏輯 CPU 的個數
[1014154@cc69dd4c5-4tdb5 ~]$ cat /proc/cpuinfo| grep "processor"| wc -l
32
top
在 Linux 核心的作業系統中,程序是根據虛拟運作時間(由程序優先級、nice 值加上實際占用的 CPU 時間進行動态計算得出)進行動态排程的。在執行程序時,需要從使用者态轉換到核心态,使用者空間不能直接操作核心空間的函數。通常要利用系統調用來完成程序排程,而使用者空間到核心空間的轉換通常是通過軟中斷來完成的。例如要進行磁盤操作,使用者态需要通過系統調用核心的磁盤操作指令,是以 CPU 消耗的時間被切分成使用者态 CPU 消耗、系統(核心) CPU 消耗,以及磁盤操作 CPU 消耗。執行程序時,需要經過一系列的操作,程序首先在使用者态執行,在執行過程中會進行程序優先級的調整(nice),通過系統調用到核心,再通過核心調用,硬中斷、軟中斷,讓硬體執行任務。執行完成之後,再從核心态傳回給系統調用,最後系統調用将結果傳回給使用者态的程序。
top 可以檢視 CPU 總體消耗,包括分項消耗,如 User,System,Idle,nice 等。Shift + H 顯示 java 線程;Shift + M 按照記憶體使用排序;Shift + P 按照 CPU 使用時間(使用率)排序;Shift + T 按照 CPU 累積使用時間排序;多核 CPU,進入 top 視圖 1,可以看到各各 CPU 的負載情況。
top - 15:24:11 up 8 days, 7:52, 1 user, load average: 5.73, 6.85, 7.33
Tasks: 17 total, 1 running, 16 sleeping, 0 stopped, 0 zombie
%Cpu(s): 13.9 us, 9.2 sy, 0.0 ni, 76.1 id, 0.1 wa, 0.0 hi, 0.1 si, 0.7 st
KiB Mem : 11962365+total, 50086832 free, 38312808 used, 31224016 buff/cache
KiB Swap: 0 total, 0 free, 0 used. 75402760 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
300 ymmapp 20 0 17.242g 1.234g 14732 S 2.3 1.1 9:40.38 java
1 root 20 0 15376 1988 1392 S 0.0 0.0 0:00.06 sh
11 root 20 0 120660 11416 1132 S 0.0 0.0 0:04.94 python
54 root 20 0 85328 2240 1652 S 0.0 0.0 0:00.00 su
55 ymmapp 20 0 17432 1808 1232 S 0.0 0.0 0:00.00 bash
56 ymmapp 20 0 17556 2156 1460 S 0.0 0.0 0:00.03 control.sh
57 ymmapp 20 0 11880 740 576 S 0.0 0.0 0:00.00 tee
115 ymmapp 20 0 17556 2112 1464 S 0.0 0.0 0:00.02 control_new_war
133 root 20 0 106032 4240 3160 S 0.0 0.0 0:00.03 sshd
134 ymmapp 20 0 17080 6872 3180 S 0.0 0.0 0:01.82 ops-updater
147 ymmapp 20 0 17956 2636 1544 S 0.0 0.0 0:00.07 control.sh
6538 ymmapp 20 0 115656 10532 3408 S 0.0 0.0 0:00.46 beidou-agent
6785 ymmapp 20 0 2572996 22512 2788 S 0.0 0.0 0:03.44 gatherinfo4dock
29241 root 20 0 142148 5712 4340 S 0.0 0.0 0:00.04 sshd
29243 1014154 20 0 142148 2296 924 S 0.0 0.0 0:00.00 sshd
29244 1014154 20 0 15208 2020 1640 S 0.0 0.0 0:00.00 bash
32641 1014154 20 0 57364 2020 1480 R 0.0 0.0 0:00.00 top
第一行:15:24:11 up 8 days, 7:52, 1 user, load average: 5.73, 6.85, 7.33:15:24:11 系統時間,up 8 days 運作時間,1 user 目前登入使用者數,load average 負載均衡情況,分别表示 1 分鐘,5 分鐘,15 分鐘負載情況。
第二行:Tasks: 17 total, 1 running, 16 sleeping, 0 stopped, 0 zombie:總程序數 17,運作數 1,休眠 16,停止 0,僵屍程序 0。
第三行:%Cpu(s): 13.9 us, 9.2 sy, 0.0 ni, 76.1 id, 0.1 wa, 0.0 hi, 0.1 si, 0.7 st:使用者空間 CPU 占比 13.9%,核心空間 CPU 占比 9.2%,改變過優先級的程序 CPU 占比 0%,空閑 CPU 占比 76.1,IO 等待占用 CPU 占比 0.1%,硬中斷占用 CPU 占比 0%,軟中斷占用 CPU 占比 0.1%, 目前 VM 中的 cpu 時鐘被虛拟化偷走的比例 0.7%。
第四和第五行表示記憶體和 swap 區域的使用情況。
第七行表示:
- 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 : 程序名稱(指令名 / 指令行)
計算在 cpu load 裡面的 uninterruptedsleep 的任務數量
top -b -n 1 | awk '{if (NR<=7)print;else if($8=="D"){print;count++}}END{print "Total status D:"count}'
[root@localhost ~]# top -b -n 1 | awk '{if (NR<=7)print;else if($8=="D"){print;count++}}END{print "Total status D:"count}'
top - 15:35:05 up 1 day, 26 min, 3 users, load average: 0.00, 0.01, 0.05
Tasks: 225 total, 1 running, 224 sleeping, 0 stopped, 0 zombie
%Cpu(s): 2.5 us, 10.0 sy, 0.0 ni, 87.5 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 1421760 total, 104516 free, 777344 used, 539900 buff/cache
KiB Swap: 2097148 total, 2071152 free, 25996 used. 456028 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
Total status D:
sar
通過 sar -u 3 可以檢視 CUP 總體消耗占比:
[root@localhost ~]# sar -u 3
Linux 3.10.0-1062.el7.x86_64 (localhost.localdomain) 2020年05月01日 _x86_64_ (2 CPU)
15時18分03秒 CPU %user %nice %system %iowait %steal %idle
15時18分06秒 all 0.00 0.00 0.17 0.00 0.00 99.83
15時18分09秒 all 0.00 0.00 0.17 0.00 0.00 99.83
15時18分12秒 all 0.17 0.00 0.17 0.00 0.00 99.66
15時18分15秒 all 0.00 0.00 0.00 0.00 0.00 100.00
15時18分18秒 all 0.00 0.00 0.00 0.00 0.00 100.00
- %user:使用者空間的 CPU 使用。
- %nice:改變過優先級的程序的 CPU 使用率。
- %system:核心空間的 CPU 使用率。
- %iowait:CPU 等待 IO 的百分比 。
- %steal:虛拟機的虛拟機 CPU 使用的 CPU。
-
%idle:空閑的 CPU。
在以上的顯示當中,主要看 %iowait 和 %idle:
- 若 %iowait 的值過高,表示硬碟存在 I/O 瓶頸;
- 若 %idle 的值高但系統響應慢時,有可能是 CPU 等待配置設定記憶體,此時應加大記憶體容量;
- 若 %idle 的值持續低于 10,則系統的 CPU 處理能力相對較低,表明系統中最需要解決的資源是 CPU;
定位線上最耗 CPU 的線程
準備工作
啟動一個程式。arthas-demo 是一個簡單的程式,每隔一秒生成一個随機數,再執行質因數分解,并列印出分解結果。
curl -O https://alibaba.github.io/arthas/arthas-demo.jar
java -jar arthas-demo.jar
[root@localhost ~]# curl -O https://alibaba.github.io/arthas/arthas-demo.jar
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 3743 100 3743 0 0 3022 0 0:00:01 0:00:01 --:--:-- 3023
[root@localhost ~]# java -jar arthas-demo.jar
1813=7*7*37
illegalArgumentCount: 1, number is: -180005, need >= 2
illegalArgumentCount: 2, number is: -111175, need >= 2
18505=5*3701
166691=7*23813
105787=11*59*163
60148=2*2*11*1367
196983=3*3*43*509
illegalArgumentCount: 3, number is: -173479, need >= 2
illegalArgumentCount: 4, number is: -112840, need >= 2
39502=2*19751
....
通過 top 指令找到最耗時的程序
[root@localhost ~]# top
top - 11:11:05 up 20:02, 3 users, load average: 0.09, 0.07, 0.05
Tasks: 225 total, 1 running, 224 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.0 us, 0.7 sy, 0.0 ni, 99.3 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 1421760 total, 135868 free, 758508 used, 527384 buff/cache
KiB Swap: 2097148 total, 2070640 free, 26508 used. 475852 avail Mem
Change delay from 3.0 to
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
98344 root 20 0 2422552 23508 12108 S 0.7 1.7 0:00.32 java
1 root 20 0 194100 6244 3184 S 0.0 0.4 0:20.41 systemd
2 root 20 0 0 0 0 S 0.0 0.0 0:00.12 kthreadd
4 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 kworker/0:0H
6 root 20 0 0 0 0 S 0.0 0.0 0:20.25 ksoftirqd/0
找到程序号是 98344。
找到程序中最耗 CUP 的線程
使用 ps -Lp #pid cu 指令,檢視某個程序中的線程 CPU 消耗排序:
[root@localhost ~]# ps -Lp 98344 cu
USER PID LWP %CPU NLWP %MEM VSZ RSS TTY STAT START TIME COMMAND
root 98344 98344 0.0 10 4.1 2422552 59060 pts/0 Sl+ 11:09 0:00 java
root 98344 98345 0.0 10 4.1 2422552 59060 pts/0 Sl+ 11:09 0:04 java
root 98344 98346 0.0 10 4.1 2422552 59060 pts/0 Sl+ 11:09 0:01 VM Thread
root 98344 98347 0.0 10 4.1 2422552 59060 pts/0 Sl+ 11:09 0:00 Reference Handl
root 98344 98348 0.0 10 4.1 2422552 59060 pts/0 Sl+ 11:09 0:00 Finalizer
root 98344 98349 0.0 10 4.1 2422552 59060 pts/0 Sl+ 11:09 0:00 Signal Dispatch
root 98344 98350 0.0 10 4.1 2422552 59060 pts/0 Sl+ 11:09 0:05 C2 CompilerThre
root 98344 98351 0.0 10 4.1 2422552 59060 pts/0 Sl+ 11:09 0:00 C1 CompilerThre
root 98344 98352 0.0 10 4.1 2422552 59060 pts/0 Sl+ 11:09 0:00 Service Thread
root 98344 98353 0.1 10 4.1 2422552 59060 pts/0 Sl+ 11:09 0:19 VM Periodic Tas
看 TIME 列可以看出那個線程耗費 CUP 多,根據 LWP 列可以看到線程的 ID 号,但是需要轉換成 16 進制才可以查詢線程堆棧資訊。
擷取線程 id 的十六進制碼
使用 printf '%x\n' 98345 指令做進制轉換:
[root@localhost ~]# printf '%x\n' 98345
18029
檢視線程堆棧資訊
使用 jstack 擷取堆棧資訊 jstack 98344 | grep -A 10 18029:
[root@localhost ~]# jstack 98344 | grep -A 10 18029
"main" #1 prio=5 os_prio=0 tid=0x00007fb88404b800 nid=0x18029 waiting on condition [0x00007fb88caab000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at java.lang.Thread.sleep(Thread.java:340)
at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386)
at demo.MathGame.main(MathGame.java:17)
"VM Thread" os_prio=0 tid=0x00007fb8840f2800 nid=0x1802a runnable
"VM Periodic Task Thread" os_prio=0 tid=0x00007fb884154000 nid=0x18031 waiting on condition
通過指令我們可以看到這個線程的對應的耗時代碼是在 demo.MathGame.main(MathGame.java:17)
grep -C 5 foo file 顯示file檔案裡比對foo字串那行以及上下5行
grep -B 5 foo file 顯示foo及前5行
grep -A 5 foo file 顯示foo及後5行
網絡瓶頸
定位丢包,錯包情況
watch more /proc/net/dev 用于定位丢包,錯包情況,以便看網絡瓶頸,重點關注 drop (包被丢棄) 和網絡包傳送的總量,不要超過網絡上限:
[root@localhost ~]# watch -n 2 more /proc/net/dev
Every 2.0s: more /proc/net/dev Fri May 1 17:16:55 2020
Inter-| Receive | Transmit
face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed
lo: 10025 130 0 0 0 0 0 0 10025 130 0 0 0 0 0 0
ens33: 759098071 569661 0 0 0 0 0 0 19335572 225551 0 0 0 0 0 0
- 最左邊的表示接口的名字,Receive 表示收包,Transmit 表示發送包;
- bytes:表示收發的位元組數;
- packets:表示收發正确的包量;
- errs:表示收發錯誤的包量;
- drop:表示收發丢棄的包量;
檢視路由經過的位址
traceroute ip 可以檢視路由經過的位址,常用來統計網絡在各個路由區段的耗時,如:
[root@localhost ~]# traceroute 14.215.177.38
traceroute to 14.215.177.38 (14.215.177.38), 30 hops max, 60 byte packets
1 CD-HZTK5H2.mshome.net (192.168.137.1) 0.126 ms * *
2 * * *
3 10.250.112.3 (10.250.112.3) 12.587 ms 12.408 ms 12.317 ms
4 172.16.227.230 (172.16.227.230) 2.152 ms 2.040 ms 1.956 ms
5 172.16.227.202 (172.16.227.202) 11.884 ms 11.746 ms 12.692 ms
6 172.16.227.65 (172.16.227.65) 2.665 ms 3.143 ms 2.923 ms
7 171.223.206.217 (171.223.206.217) 2.834 ms 2.752 ms 2.654 ms
8 182.150.18.205 (182.150.18.205) 5.145 ms 5.815 ms 5.542 ms
9 110.188.6.33 (110.188.6.33) 3.514 ms 171.208.199.185 (171.208.199.185) 3.431 ms 171.208.199.181 (171.208.199.181) 10.768 ms
10 202.97.29.17 (202.97.29.17) 29.574 ms 202.97.30.146 (202.97.30.146) 32.619 ms *
11 113.96.5.126 (113.96.5.126) 36.062 ms 113.96.5.70 (113.96.5.70) 35.940 ms 113.96.4.42 (113.96.4.42) 45.859 ms
12 90.96.135.219.broad.fs.gd.dynamic.163data.com.cn (219.135.96.90) 35.680 ms 35.468 ms 35.304 ms
13 14.215.32.102 (14.215.32.102) 35.135 ms 14.215.32.110 (14.215.32.110) 35.613 ms 14.29.117.242 (14.29.117.242) 54.712 ms
14 * 14.215.32.134 (14.215.32.134) 49.518 ms 14.215.32.122 (14.215.32.122) 47.652 ms
15 * * *
...
檢視網絡錯誤
netstat -i 可以檢視網絡錯誤:
[root@localhost ~]# netstat -i
Kernel Interface table
Iface MTU RX-OK RX-ERR RX-DRP RX-OVR TX-OK TX-ERR TX-DRP TX-OVR Flg
ens33 1500 570291 0 0 0 225897 0 0 0 BMRU
lo 65536 130 0 0 0 130 0 0 0 LRU
- Iface: 網絡接口名稱;
- MTU: 最大傳輸單元,它限制了資料幀的最大長度,不同的網絡類型都有一個上限值,如:以太網的 MTU 是 1500;
- RX-OK:接收時,正确的資料包數。
- RX-ERR``==:接收時,産生錯誤的資料包數。
- RX-DRP:接收時,丢棄的資料包數。
- RX-OVR:接收時,由于過速(在資料傳輸中,由于接收裝置不能接收按照發送速率傳送來的資料而使資料丢失)而丢失的資料包數。
- TX-OK:發送時,正确的資料包數。
- TX-ERR:發送時,産生錯誤的資料包數。
- TX-DRP:發送時,丢棄的資料包數。
- TX-OVR:發送時,由于過速而丢失的資料包數。
- Flg:标志,B 已經設定了一個廣播位址。L 該接口是一個回送裝置。M 接收所有資料包(混亂模式)。N 避免跟蹤。O 在該接口上,禁用 ARP。P 這是一個點到點連結。R 接口正在運作。U 接口處于 “活動” 狀态。
包的重傳率
cat /proc/net/snmp 用來檢視和分析 240 秒内網絡包量,流量,錯包,丢包。通過 RetransSegs 和 OutSegs 來計算重傳率 tcpetr=RetransSegs/OutSegs。
[root@localhost ~]# cat /proc/net/snmp
Ip: Forwarding DefaultTTL InReceives InHdrErrors InAddrErrors ForwDatagrams InUnknownProtos InDiscards InDelivers OutRequests OutDiscards OutNoRoutes ReasmTimeout ReasmReqds ReasmOKs ReasmFails FragOKs FragFails FragCreates
Ip: 1 64 241708 0 0 0 0 0 238724 225517 15 0 0 0 0 0 0 0 0
Icmp: InMsgs InErrors InCsumErrors InDestUnreachs InTimeExcds InParmProbs InSrcQuenchs InRedirects InEchos InEchoReps InTimestamps InTimestampReps InAddrMasks InAddrMaskReps OutMsgs OutErrors OutDestUnreachs OutTimeExcds OutParmProbs OutSrcQuenchs OutRedirects OutEchos OutEchoReps OutTimestamps OutTimestampReps OutAddrMasks OutAddrMaskReps
Icmp: 149 0 0 50 99 0 0 0 0 0 0 0 0 0 147 0 147 0 0 0 0 0 0 0 0 0 0
IcmpMsg: InType3 InType11 OutType3
IcmpMsg: 50 99 147
Tcp: RtoAlgorithm RtoMin RtoMax MaxConn ActiveOpens PassiveOpens AttemptFails EstabResets CurrEstab InSegs OutSegs RetransSegs InErrs OutRsts InCsumErrors
Tcp: 1 200 120000 -1 376 6 0 0 4 236711 223186 292 0 4 0
Udp: InDatagrams NoPorts InErrors OutDatagrams RcvbufErrors SndbufErrors InCsumErrors
Udp: 1405 438 0 1896 0 0 0
UdpLite: InDatagrams NoPorts InErrors OutDatagrams RcvbufErrors SndbufErrors InCsumErrors
UdpLite: 0 0 0 0 0 0 0
重傳率 = 292/223186≈0.13%
- 平均每秒新增 TCP 連接配接數:通過 /proc/net/snmp 檔案得到最近 240 秒内 PassiveOpens 的增量,除以 240 得到每秒的平均增量;
- 機器的 TCP 連接配接數 :通過 /proc/net/snmp 檔案的 CurrEstab 得到 TCP 連接配接數;
- 平均每秒的 UDP 接收資料報:通過 /proc/net/snmp 檔案得到最近 240 秒内 InDatagrams 的增量,除以 240 得到平均每秒的 UDP 接收資料報;
- 平均每秒的 UDP 發送資料報:通過 /proc/net/snmp 檔案得到最近 240 秒内 OutDatagrams 的增量,除以 240 得到平均每秒的 UDP 發送資料報;
磁盤瓶頸
檢視磁盤剩餘空間
檢視磁盤剩餘空間使用 df -hl 指令:
[root@localhost ~]# df -hl
檔案系統 容量 已用 可用 已用% 挂載點
devtmpfs 678M 0 678M 0% /dev
tmpfs 695M 0 695M 0% /dev/shm
tmpfs 695M 28M 667M 4% /run
tmpfs 695M 0 695M 0% /sys/fs/cgroup
/dev/mapper/centos_aubin-root 27G 5.6G 22G 21% /
/dev/sda1 1014M 211M 804M 21% /boot
檢視磁盤已使用空間
du -sh 指令是檢視磁盤已使用空間的情況,這裡的 “已使用的磁盤空間” 意思是指定的檔案下的整個檔案層次結構所使用的空間,在沒給定參數的情況下,du 報告目前目錄所使用的磁盤空間。其實就是顯示檔案或目錄所占用的磁盤空間的情況:
[root@localhost ~]# du -sh
64K
- -h:輸出檔案系統分區使用的情況,例如:10KB,10MB,10GB 等。
- -s:顯示檔案或整個目錄的大小,預設機關是 KB。
du 的詳細資訊可以通過 man du 檢視。
檢視磁盤讀寫情況
檢視磁盤總體讀寫情況
通 iostat 檢視磁盤總體的讀寫情況:
[root@localhost ~]# iostat
Linux 3.10.0-1062.el7.x86_64 (localhost.localdomain) 2020年05月02日 _x86_64_ (2 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
0.17 0.00 0.20 0.46 0.00 99.17
Device: tps kB_read/s kB_wrtn/s kB_read kB_wrtn
sda 1.56 30.45 39.61 4659620 6060644
scd0 0.00 0.02 0.00 3102 0
dm-0 1.96 30.01 38.42 4591998 5878155
dm-1 0.09 0.09 0.30 13840 45328
- tps:該裝置每秒的傳輸次數。
- kB_read/s:每秒從裝置(drive expressed)讀取的資料量;
- kB_wrtn/s:每秒向裝置(drive expressed)寫入的資料量;
- kB_read:讀取的總資料量;
- kB_wrtn:寫入的總數量資料量;
檢視磁盤詳細讀寫情況
通過 iostat -x 1 3 可以看到磁盤詳細讀寫情況,沒隔一秒輸出一次一共輸出 3 次,當看到 I/O 等待時間所占 CPU 時間的比重很高的時候,首先要檢查的就是機器是否正在大量使用交換空間,同時關注 iowait 占比 cpu 的消耗是否很大,如果大說明磁盤存在大的瓶頸,同時關注 await,表示磁盤的響應時間以便小于 5ms:
[root@localhost ~]# iostat -x 1 3
Linux 3.10.0-1062.el7.x86_64 (localhost.localdomain) 2020年05月02日 _x86_64_ (2 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
0.17 0.00 0.20 0.46 0.00 99.16
Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
sda 0.01 0.49 0.63 0.95 30.59 39.78 89.58 0.34 214.23 49.16 323.48 8.55 1.34
scd0 0.00 0.00 0.00 0.00 0.02 0.00 98.48 0.00 1.21 1.21 0.00 0.95 0.00
dm-0 0.00 0.00 0.62 1.35 30.15 38.59 69.70 0.91 460.67 49.12 648.54 6.66 1.31
dm-1 0.00 0.00 0.02 0.07 0.09 0.30 8.52 0.04 442.74 95.43 521.17 6.91 0.06
avg-cpu 表示總體 cpu 使用情況統計資訊,對于多核 cpu,這裡為所有 cpu 的平均值:
- %user:CPU 處在使用者模式下的時間百分比。
- %nice:CPU 處在帶 NICE 值的使用者模式下的時間百分比。
- %system:CPU 處在系統模式下的時間百分比。
- %iowait:CPU 等待輸入輸出完成時間的百分比,如果 % iowait 的值過高,表示硬碟存在 I/O 瓶頸。
- %steal:管理程式維護另一個虛拟處理器時,虛拟 CPU 的無意識等待時間百分比。
- %idle:CPU 空閑時間百分比,如果 % idle 值高,表示 CPU 較空閑;如果 % idle 值高但系統響應慢時,可能是 CPU 等待配置設定記憶體,應加大記憶體容量;如果 % idle 值持續低于 10,表明 CPU 處理能力相對較低,系統中最需要解決的資源是 CPU。。
Device 表示裝置資訊:
- rrqm/s:每秒對該裝置的讀請求被合并次數,檔案系統會對讀取同塊 (block) 的請求進行合并
- wrqm/s:每秒對該裝置的寫請求被合并次數
- r/s:每秒完成的讀次數
- w/s:每秒完成的寫次數
- rkB/s:每秒讀資料量 (kB 為機關)
- wkB/s:每秒寫資料量 (kB 為機關)
- avgrq-sz:平均每次 IO 操作的資料量 (扇區數為機關)
- avgqu-sz:平均等待處理的 IO 請求隊列長度
- await:平均每次 IO 請求等待時間 (包括等待時間和處理時間,毫秒為機關)
- svctm:平均每次 IO 請求的處理時間 (毫秒為機關)
- %util:一秒中有百分之多少的時間用于 I/O 如果 % util 接近 100%,說明産生的 I/O 請求太多,I/O 系統已經滿負荷。idle 小于 70% IO 壓力就較大了,一般讀取速度有較多的 wait。
iostat -xmd 1 3:新增 m 選項可以在輸出是使用 M 為機關。
檢視最耗 IO 的程序
一般先通過 iostat 檢視是否存在 io 瓶頸,再使用 iotop 指令來定位那個程序最耗費 IO:
[root@localhost ~]# iotop
Total DISK READ : 0.00 B/s | Total DISK WRITE : 0.00 B/s
Actual DISK READ: 0.00 B/s | Actual DISK WRITE: 0.00 B/s
TID PRIO USER DISK READ DISK WRITE SWAPIN IO> COMMAND
123931 be/4 root 0.00 B/s 0.00 B/s 0.00 % 0.02 % [kworker/1:30]
94208 be/4 xiaolyuh 0.00 B/s 0.00 B/s 0.00 % 0.00 % nautilus-desktop --force [gmain]
1 be/4 root 0.00 B/s 0.00 B/s 0.00 % 0.00 % systemd --system --deserialize 62
2 be/4 root 0.00 B/s 0.00 B/s 0.00 % 0.00 % [kthreadd]
94211 be/4 xiaolyuh 0.00 B/s 0.00 B/s 0.00 % 0.00 % gvfsd-trash --spawner :1.4 /org/gtk/gvfs/exec_spaw/0
4 be/0 root 0.00 B/s 0.00 B/s 0.00 % 0.00 % [kworker/0:0H]
6 be/4 root 0.00 B/s 0.00 B/s 0.00 % 0.00 % [ksoftirqd/0]
7 rt/4 root 0.00 B/s 0.00 B/s 0.00 % 0.00 % [migration/0]
8 be/4 root 0.00 B/s 0.00 B/s 0.00 % 0.00 % [rcu_bh]
9 be/4 root 0.00 B/s 0.00 B/s 0.00 % 0.00 % [rcu_sched]
10 be/0 root 0.00 B/s 0.00 B/s 0.00 % 0.00 % [lru-add-drain]
...
通過 iotop -p pid 可以檢視單個程序的 IO 情況:
[root@localhost ~]# iotop -p 124146
Total DISK READ : 0.00 B/s | Total DISK WRITE : 0.00 B/s
Actual DISK READ: 0.00 B/s | Actual DISK WRITE: 0.00 B/s
TID PRIO USER DISK READ DISK WRITE SWAPIN IO> COMMAND
124146 be/4 root 0.00 B/s 0.00 B/s 0.00 % 0.00 % java -jar arthas-demo.jar
應用瓶頸
檢視某個程序的 PID
如檢視 java 的程序的 pid,ps -ef | grep java:
[root@localhost ~]# ps -ef | grep java
root 124146 1984 0 09:13 pts/0 00:00:06 java -jar arthas-demo.jar
root 125210 98378 0 10:07 pts/1 00:00:00 grep --color=auto java
檢視特定程序的數量
如檢視 java 程序的數量,ps -ef | grep java| wc -l:
[root@localhost ~]# ps -ef | grep java| wc -l
2
檢視線程是否存在死鎖
檢視線程是否存在死鎖,jstack -l pid:
[root@localhost ~]# jstack -l 124146
2020-05-02 10:13:38
Full thread dump OpenJDK 64-Bit Server VM (25.252-b09 mixed mode):
"C1 CompilerThread1" #6 daemon prio=9 os_prio=0 tid=0x00007f27f013c000 nid=0x1e4f9 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"C2 CompilerThread0" #5 daemon prio=9 os_prio=0 tid=0x00007f27f012d000 nid=0x1e4f8 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"main" #1 prio=5 os_prio=0 tid=0x00007f27f004b800 nid=0x1e4f3 waiting on condition [0x00007f27f7274000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at java.lang.Thread.sleep(Thread.java:340)
at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386)
at demo.MathGame.main(MathGame.java:17)
Locked ownable synchronizers:
- None
...
檢視某個程序的線程數
ps -efL | grep [PID] | wc -l,如:
[root@localhost ~]# ps -efL | grep 124146 | wc -l
12
檢視具體有哪些線程用 ps -Lp [pid] cu:
[root@localhost ~]# ps -Lp 124146 cu
USER PID LWP %CPU NLWP %MEM VSZ RSS TTY STAT START TIME COMMAND
root 124146 124146 0.0 11 2.5 2489116 35724 pts/0 Sl+ 09:13 0:00 java
root 124146 124147 0.0 11 2.5 2489116 35724 pts/0 Sl+ 09:13 0:01 java
root 124146 124148 0.0 11 2.5 2489116 35724 pts/0 Sl+ 09:13 0:00 VM Thread
root 124146 124149 0.0 11 2.5 2489116 35724 pts/0 Sl+ 09:13 0:00 Reference Handl
root 124146 124150 0.0 11 2.5 2489116 35724 pts/0 Sl+ 09:13 0:00 Finalizer
root 124146 124151 0.0 11 2.5 2489116 35724 pts/0 Sl+ 09:13 0:00 Signal Dispatch
root 124146 124152 0.0 11 2.5 2489116 35724 pts/0 Sl+ 09:13 0:00 C2 CompilerThre
root 124146 124153 0.0 11 2.5 2489116 35724 pts/0 Sl+ 09:13 0:00 C1 CompilerThre
root 124146 124154 0.0 11 2.5 2489116 35724 pts/0 Sl+ 09:13 0:00 Service Thread
root 124146 124155 0.1 11 2.5 2489116 35724 pts/0 Sl+ 09:13 0:05 VM Periodic Tas
root 124146 125362 0.0 11 2.5 2489116 35724 pts/0 Sl+ 10:13 0:00 Attach Listener
統計所有的 log 檔案中,包含 Error 字元的行
find / -type f -name "*.log" | xargs grep "ERROR",這個在排查問題過程中比較有用:
[root@localhost ~]# find / -type f -name "*.log" | xargs grep "ERROR"
/var/log/tuned/tuned.log:2020-03-13 18:05:59,145 ERROR tuned.utils.commands: Writing to file '/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor' error: '[Errno 19] No such device'
/var/log/tuned/tuned.log:2020-03-13 18:05:59,145 ERROR tuned.utils.commands: Writing to file '/sys/devices/system/cpu/cpu1/cpufreq/scaling_governor' error: '[Errno 19] No such device'
/var/log/tuned/tuned.log:2020-04-28 14:55:34,857 ERROR tuned.utils.commands: Writing to file '/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor' error: '[Errno 19] No such device'
/var/log/tuned/tuned.log:2020-04-28 14:55:34,859 ERROR tuned.utils.commands: Writing to file '/sys/devices/system/cpu/cpu1/cpufreq/scaling_governor' error: '[Errno 19] No such device'
/var/log/tuned/tuned.log:2020-04-28 15:23:19,037 ERROR tuned.utils.commands: Writing to file '/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor' error: '[Errno 19] No such device'
...
應用啟動時指定 JVM 參數
java -jar -Xms128m -Xmx1024m -Xss512k -XX:PermSize=128m -XX:MaxPermSize=64m -XX:NewSize=64m -XX:MaxNewSize=256m arthas-demo.jar,如:
[root@localhost ~]# java -jar -Xms128m -Xmx1024m -Xss512k -XX:PermSize=128m -XX:MaxPermSize=64m -XX:NewSize=64m -XX:MaxNewSize=256m arthas-demo.jar
OpenJDK 64-Bit Server VM warning: ignoring option PermSize=128m; support was removed in 8.0
OpenJDK 64-Bit Server VM warning: ignoring option MaxPermSize=64m; support was removed in 8.0
157518=2*3*3*3*2917
illegalArgumentCount: 1, number is: -187733, need >= 2
illegalArgumentCount: 2, number is: -102156, need >= 2
173379=3*57793
總結
在使用 linux 指令時,如果想看幫助可以使用 --help 或者 man 檢視幫助資訊:
[root@localhost ~]# grep --help
用法: grep [選項]... PATTERN [FILE]...
在每個 FILE 或是标準輸入中查找 PATTERN。
預設的 PATTERN 是一個基本正規表達式(縮寫為 BRE)。
例如: grep -i 'hello world' menu.h main.c
...
[root@localhost ~]# man grep
GREP(1) General Commands Manual GREP(1)
NAME
grep, egrep, fgrep - 列印比對給定模式的行
總覽 SYNOPSIS
grep [options] PATTERN [FILE...]
grep [options] [-e PATTERN | -f FILE] [FILE...]
描述 DESCRIPTION
Grep 搜尋以 FILE 命名的檔案輸入 (或者是标準輸入,如果沒有指定檔案名,或者給出的檔案名是 - 的話),尋找含有與給定的模式 PATTERN
...
類别 | 監控指令 | 描述 | 備注 |
記憶體瓶頸 | free | 檢視記憶體使用 | |
vmstat 3 (間隔時間) 100 (監控次數) | 檢視 swap in/out 詳細定位是否存在性能瓶頸 | 推薦使用 | |
sar -r 3 | 和 free 指令類似,檢視記憶體的使用情況,但是不包含 swap 的情況 | ||
cpu 瓶頸 | top -H | 按照 cpu 消耗高低進行排序 | |
ps -Lp 程序号 cu | 檢視某個程序的 cpu 消耗排序 | ||
cat /proc/cpuinfo |grep ‘processor’|wc -l | 檢視 cpu 核數 | ||
top | 檢視 cpu 總體消耗,包括分項消耗如 user,system,idle,nice 等消耗 | ||
top 然後 shift+h: 顯示 java 線程,然後 shift+M: 按照記憶體使用進行排序;shift+P: 按照 cpu 時間排序;shift+T: 按照 cpu 累計使用時間排序多核 cpu,按 “1” 進入 top 視圖 | 專項性能排查,多核 CPU 主要看 CUP 各個核心的負載情況 | ||
sar -u 3 (間隔時間) | 檢視 cpu 總體消耗占比 | ||
sar -q | 檢視 cpu load | ||
top -b -n 1 | awk ‘{if (NR<=7)print;else if($8==“D”){print;count++}}END{print "Total status D:"count}’ | 計算在 cpu load 裡面的 uninterruptedsleep 的任務數量 uninterruptedsleep 的任務會被計入 cpu load,如磁盤堵塞 | ||
網絡瓶頸 | cat /var/log/messages | 檢視核心日志,檢視是否丢包 | |
watch more /proc/net/dev | 用于定位丢包,錯包情況,以便看網絡瓶頸 | 重點關注 drop (包被丢棄) 和網絡包傳送的總量,不要超過網絡上限 | |
sar -n SOCK | 檢視網絡流量 | ||
netstat -na|grep ESTABLISHED|wc -l | 檢視 tcp 連接配接成功狀态的數量 | 此指令特别消耗 cpu,不适合進行長時間監控資料收集 | |
netstat -na|awk’{print $6}'|sort |uniq -c |sort -nr | 看 tcp 各個狀态數量 | ||
netstat -i | 檢視網絡錯誤 | ||
ss state ESTABLISHED| wc -l | 更高效地統計 tcp 連接配接狀态為 ESTABLISHED 的數量 | ||
cat /proc/net/snmp | 檢視和分析 240 秒内網絡包量,流量,錯包,丢包 | 用于計算重傳率 tcpetr=RetransSegs/OutSegs | |
ping $ip | 測試網絡性能 | ||
dmesg | 檢視系統核心日志 | ||
磁盤瓶頸 | iostat -x -k -d 1 | 詳細列出磁盤的讀寫情況 | 當看到 I/O 等待時間所占 CPU 時間的比重很高的時候,首先要檢查的就是機器是否正在大量使用交換空間,同時關注 iowait 占比 cpu 的消耗是否很大,如果大說明磁盤存在大的瓶頸,同時關注 await,表示磁盤的響應時間以便小于 5ms |
iostat -x | 檢視系統各個磁盤的讀寫性能 | 重點關注 await 和 iowait 的 cpu 占比 | |
iotop | 檢視哪個程序在大量讀取 IO | 一般先通過 iostat 檢視是否存在 io 瓶頸,再定位哪個程序在大量讀取 IO | |
df -hl | 檢視磁盤剩餘空間 | ||
du -sh | 檢視磁盤使用了多少空間 | ||
應用瓶頸 | ps -ef | grep java | 檢視某個程序的 id 号 |
ps -ef | grep httpd| wc -l | 檢視特定程序的數量 | ||
cat ***.log | grep ***Exception| wc -l | 統計日志檔案中包含特定異常數量 | ||
jstack -l pid | 用于檢視線程是否存在死鎖 | ||
awk’{print $8}’ 2017-05-22-access_log|egrep ‘301|302’| wc -l | 統計 log 中 301、302 狀态碼的行數,$8 表示第八列是狀态碼,可以根據實際情況更改 | 常用于應用故障定位 | |
grep ‘wholesaleProductDetailNew’ cookie_log | awk '{if($10==“200”)}‘print}’ | awk ‘print $12’ | more | 列印包含特定資料的 12 列資料 | |
grep “2017:05:22” cookielog | awk ‘($12>0.3){print 8}’ | sort > 目錄位址 | 對 apache 或者 nginx 通路 log 進行響應時間排序,$12 表示 cookie log 中的 12 清單示響應時間 用于排查是否是由于是某些通路超長造成整體的 RT 變長 | ||
grep -v ‘HTTP/1.1" 200’ | 取出非 200 響應碼的 URL | ||
pgm -A -f $ 應用叢集名稱 “grep”‘301’ log 檔案位址 | wc -l" | 檢視整個叢集的 log 中 301 狀态碼的數量 | ||
ps -efL | grep [PID] | wc -l | 檢視某個程序建立的線程數 | ||
find / -type f -name “*.log” | xargs grep “ERROR” | 統計所有的 log 檔案中,包含 Error 字元的行 | 這個在排查問題過程中比較有用 | |
jstat -gc [pid] | 檢視 gc 情況 | ||
jstat -gcnew [pid] | 檢視 young 區的記憶體使用情況,包括 MTT (最大互動次數就被交換到 old 區),TT 是目前已經交換的次數 | ||
jstat -gcold | 檢視 old 區的記憶體使用情況 | ||
jmap -J-d64 -dump:format=b,file=dump.bin PID | dump 出記憶體快照 | -J-d64 防止 jmap 導緻虛拟機 crash (jdk6 有 bug) | |
-XX:+HeapDumpOnOutOfMemeryError | 在 java 啟動時加入,當出現記憶體溢出時,存儲記憶體快照 | ||
jmap -histo [pid] | 按照對象記憶體大小排序 | 注意會導緻 full gc | |
gcore [pid] | 導出完成的記憶體快照 | 通常和 jmap -permstat /opt/**/java gcore.bin 一起使用,将 core dump 轉換成 heap dump | |
-XX:HeapDumpPath=/home/logs -Xloggc:/home/log/gc.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps | 在 Java 啟動參數中加入,列印 gc 日志 | ||
-server -Xms4000m -Xmx4000m -Xmn1500m -Xss256k -XX:PermSize=340m -XX:MaxPermSize=340m -XX:+UseConcMarkSweepGC | 調整 JVM 堆大小 | xss 是棧大小 |