Java後端線上問題排查常用命令收藏

作者 | xiaolyuh

來源 | http://r6d.cn/b97q7
內存瓶頸

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秒內網絡包量,流量,錯包,丟包。通過RetransSegsOutSegs來計算重傳率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 測試網絡性能

traceroute $ip 查看路由經過的地址 常用於定位網絡在各個路由區段的耗時

dig $域名 查看域名解析地址

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是棧大小


Java API版權第一大案,索賠百億美元,打了10年終於有結果了!



往期推薦

Java API版權第一大案,索賠百億美元,打了10年終於有結果了!

聽說過OpenJDK,沒說過OpenValueJDK吧?

2021 年4月數據庫流行度排行榜出爐!Snowflake 和 Clickhouse上升迅速!

2021年3月程序員工資統計數據出爐,又拖後腿了……

漲姿勢:另類的表情域名賺錢大法!!


如果你喜歡本文,歡迎關注我,訂閱更多精彩內容
關注我回復「加羣」,加入Spring技術交流羣

免費領取:字節跳動資料-圖解網絡


喜歡的這裏報道

↘↘↘

本文分享自微信公衆號 - 程序猿DD(didispace)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章