性能問題分析過程

原文鏈接:https://www.cnblogs.com/xiaoxitest/protected/p/9049799.html

一、CPU使用率分析過程

查找是用戶進程CPU高還是系統CPU進程高
如果是用戶進程CPU高,查找哪個進程高,再查哪個線程,看這個線程執行的方法或請求,(該方法或請求就是導致CPU高的原因)
如果是系統CPU高,看是不是系統調用導致了CPU比較高,看IO繁忙導致的,是否有排隊現象
查看磁盤讀寫操作,讀操作多 可能是內存不足導致,內存不足導致磁盤頻繁讀數據,寫操作多, 看操作系統在寫什麼
如果不是磁盤讀寫問題,用strace看調用哪個內核,看哪個請求調用這個內核

1、查看佔用CPU最多的進程
ps命令查看
linux下獲取佔用CPU資源最多的10個進程,可以使用如下命令組合:
ps aux | head -1;ps aux | grep -v PID | sort -rn -k +3 | head
在這裏插入圖片描述
該命令組合實際上是下面兩句命令:
ps aux|head -1
ps aux|grep -v PID|sort -rn -k +3|head

top命令查看
top命令查看CPU資源佔用最多的進程:
top -c 進入監控狀態,按Shift+p按照CPU使用率排序:
在這裏插入圖片描述
2、查看該進程下佔用CPU時間最長的線程:

top命令查看

top -Hp 1584 進入線程監控狀態後,按Shift+t 按照CPU使用時間進行排序:
在這裏插入圖片描述
ps命令查看

ps -mp 1584 -o THREAD,tid,time | sort -rn
在這裏插入圖片描述
對CPU使用率過高的進程中的所有線程進行排序,命令如下:
ps H -e -opid,tid,pcpu,cmd --sort=pcpu | grep 1584
在這裏插入圖片描述
3、將線程ID轉爲爲十六進制

linux下轉換:printf ‘%x\n’ 1933
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
4、jstack查看線程棧狀態

jstack 1584 | grep 78d -A 10  (1584爲PID,78d爲線程id,字母需小寫)
在這裏插入圖片描述
5、把線程棧輸出到本地
jstack 1584 > 1.txt
vim 1.txt
查看是否有block 線程死鎖
大量waiting線程,等待的資源造成系統瓶頸的原因,如數據庫連接池等待

二、內存分析

1、查看內存佔用最高的進程

ps命令查看

ps -e -o ‘pid,comm,args,pcpu,rsz,vsz,stime,user,uid’ | grep java | sort -nrk5  #java爲你要顯示的服務
在這裏插入圖片描述
其中rsz爲實際內存,上例實現按內存排序,由大到小
top命令查看

top -c 進入監控狀態,按Shift+m按照內存使用率排序:
在這裏插入圖片描述
2、查看java堆內存佔用,由高到低並輸出到文件

jmap -histo pid > 1.txt
在這裏插入圖片描述
3、監測內存使用情況
每2秒1次,共5次
jstat -gcutil 1584 2000 5
在這裏插入圖片描述
4、下載堆內存到本地

jmap -dump:live,format=b,file=heap.bin
在這裏插入圖片描述
5、分析內存使用情況
將下載的堆內存使用MemoryAnalyzer 打開進行分析
在這裏插入圖片描述
三、查看tcp連接
查看所有tcp連接:
netstat -n | awk ‘/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}’在這裏插入圖片描述
查看指定端口tcp連接:
在這裏插入圖片描述
統計每個IP的連接數:

netstat -n | awk ‘/^tcp/ {print $5}’ | awk -F: ‘{print $1}’ | sort | uniq -c| sort -rn
在這裏插入圖片描述
TCP連接狀態詳解:

發起握手階段

CLOSED:初始狀態,表示TCP連接是“關閉着的”或“未打開的”。

LISTEN :表示服務器端的某個SOCKET處於監聽狀態,可以接受客戶端的連接。

SYN_RCVD:表示接受到了SYN報文,在正常情況下,這個狀態是服務器端的SOCKET在建立TCP連接時的三次握手會話過程中的一箇中間狀態,很短暫,基本上用netstat你是很難看到這種狀態的,除非你特意寫了一個客戶端測試程序,故意將三次TCP握手過程中最後一個ACK報文不予發送。因此這種狀態時,當收到客戶端的ACK報文後,它會進入到ESTABLISHED狀態。

SYN_SENT :這個狀態與SYN_RCVD 狀態相呼應,當客戶端SOCKET執行connect()進行連接時,它首先發送SYN報文,然後隨即進入到SYN_SENT 狀態,並等待服務端的發送三次握手中的第2個報文。SYN_SENT 狀態表示客戶端已發送SYN報文。

ESTABLISHED:表示連接已經建立,這是雙方進行正常通信所處的狀態。

主動關閉階段

FIN_WAIT_1 :其實FIN_WAIT_1 和FIN_WAIT_2 兩種狀態的真正含義都是表示等待對方的FIN報文。而這兩種狀態的區別是:FIN_WAIT_1狀態實際上是當SOCKET在ESTABLISHED狀態時,它想主動關閉連接,向對方發送了FIN報文,此時該SOCKET進入到FIN_WAIT_1 狀態。而當對方迴應ACK報文後,則進入到FIN_WAIT_2 狀態。當然在實際的正常情況下,無論對方處於任何種情況下,都應該馬上回應ACK報文,所以FIN_WAIT_1 狀態一般是比較難見到的,而FIN_WAIT_2 狀態有時仍可以用netstat看到。

FIN_WAIT_2 :上面已經解釋了這種狀態的由來,實際上FIN_WAIT_2狀態下的SOCKET表示半連接,即有一方調用close()主動要求關閉連接。注意:FIN_WAIT_2 是沒有超時的(不像TIME_WAIT 狀態),這種狀態下如果對方不關閉(不配合完成4次揮手過程),那這個 FIN_WAIT_2 狀態將一直保持到系統重啓,越來越多的FIN_WAIT_2 狀態會導致內核crash。

TIME_WAIT :表示收到了對方的FIN報文,併發送出了ACK報文。 TIME_WAIT狀態下的TCP連接會等待2*MSL(Max Segment Lifetime,最大分段生存期,指一個TCP報文在Internet上的最長生存時間。每個具體的TCP協議實現都必須選擇一個確定的MSL值,RFC 1122建議是2分鐘,但BSD傳統實現採用了30秒,Linux可以cat /proc/sys/net/ipv4/tcp_fin_timeout看到本機的這個值),然後即可回到CLOSED 可用狀態了。如果FIN_WAIT_1狀態下,收到了對方同時帶FIN標誌和ACK標誌的報文時,可以直接進入到TIME_WAIT狀態,而無須經過FIN_WAIT_2狀態。(這種情況應該就是四次揮手變成三次揮手的那種情況)

CLOSING :這種狀態在實際情況中應該很少見,屬於一種比較罕見的例外狀態。正常情況下,當一方發送FIN報文後,按理來說是應該先收到(或同時收到)對方的ACK報文,再收到對方的FIN報文。但是CLOSING 狀態表示一方發送FIN報文後,並沒有收到對方的ACK報文,反而卻也收到了對方的FIN報文。什麼情況下會出現此種情況呢?那就是當雙方幾乎在同時close()一個SOCKET的話,就出現了雙方同時發送FIN報文的情況,這是就會出現CLOSING 狀態,表示雙方都正在關閉SOCKET連接。

被動關閉階段

CLOSE_WAIT :表示正在等待關閉。怎麼理解呢?當對方close()一個SOCKET後發送FIN報文給自己,你的系統毫無疑問地將會迴應一個ACK報文給對方,此時TCP連接則進入到CLOSE_WAIT狀態。接下來呢,你需要檢查自己是否還有數據要發送給對方,如果沒有的話,那你也就可以close()這個SOCKET併發送FIN報文給對方,即關閉自己到對方這個方向的連接。有數據的話則看程序的策略,繼續發送或丟棄。簡單地說,當你處於CLOSE_WAIT 狀態下,需要完成的事情是等待你去關閉連接。

LAST_ACK :當被動關閉的一方在發送FIN報文後,等待對方的ACK報文的時候,就處於LAST_ACK 狀態。當收到對方的ACK報文後,也就可以進入到CLOSED 可用狀態了。

四、查看I/O使用情況

1、安裝iostat命令,如已安裝請忽略

yum -y install sysstat
2、iostat -x -k
在這裏插入圖片描述
以上各列的含義如下:

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: 採用週期內用於IO操作的時間比率,即IO隊列非空的時間比率

對於以上示例輸出,我們可以獲取到以下信息:

每秒向磁盤上寫3.8k左右數據(wkB/s值)
每秒有0.8次IO操作(r/s+w/s),其中以寫操作爲主體
平均每次IO請求等待處理的時間爲11.87毫秒,處理耗時爲4.75毫秒
等待處理的IO請求隊列中,平均有0.01個請求駐留

以上各值之間也存在聯繫,我們可以由一些值計算出其他數值,例如:
util = (r/s+w/s) * (svctm/1000)
對於上面的例子有:util = (0.01+0.79)*(4.75/1000) = 0.0038

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