記一次準生產問題----cpu拉滿排查

昨天週五臨下班了,心想加了一週班,今天如果不出意外的話...咳咳,不能說不能說(flag不能亂立),測試人員說系統很卡,然後去找運維,運維說機器cpu直接拉滿,我方了,因爲最後他測的功能是我寫的,果然準時下班是不存在的,登上服務器,因爲在docker裏面,所以這java進程無疑就是我們的的項目,證據確鑿

然後火速排查解決,原因是一個參數傳漏了,導致一張幾十萬的表join另一張幾十萬的表全查,boom...敲

今天分享一下排查思路。

假如生產出現CPU佔用過高,談談分析思路和問題定位?(結合linux命令和jdk命令)

[0].我們先模擬出一個生產CPU高佔用的問題,將其放在服務器上運行

javac -d . ProduceProblemPosition.java

java com.w4xj.problemposition.ProduceProblemPosition

java代碼如下,這裏只是寫一個簡單的示例

package com.w4xj.problemposition

import java.util.Random;

import java.util.UUID;



/**

* @Author by w4xj

* @Classname ProduceProblemPosition

* @Description 模擬生產問題定位

* @Date

* @Created by IDEA

*/

public class ProduceProblemPosition {

    public static void main(String[] args) {

        while(true){

            System.out.println(UUID.randomUUID().toString().substring(0,8) + " *^_^* " + new Random().nextInt(99999));

        }

    }

}

[1].先用top命令找出CPU佔用最高的程序,得知其是一個java程序,並知道其pid

[2].ps -ef 或者 jps進一步定位,得知是一個怎樣後臺程序佔用CPU

[3].定位到具體線程或者代碼

①.ps -mp 進程 -o THREAD,tid,time

②.參數

-m 顯示所有的線程

-p pid進程使用cpu的時間

-o 用戶自定義輸出格式

[4].將需要的線程id轉換爲16進制格式(英文小寫格式)

2376 -> 948

方式①.printf "%x\n" 2376

方式②.計算器

[5].jstack 進程id | grep tid(16進制小寫英文) -A60

①.找到本公司的包名的類,定位到java類的行數

②.查看源文件

另外分享一些常用的服務器排查命令

1.生產服務器變慢,診斷思路和不同的緯度

[1].整機:top

①.load average:系統負載,三個數值若平均值大於60%,則表示系統壓力過大

②.精簡版:uptime

[2].CPU:vmstat

①.查看cpu(包含但不限於),vmstat -n 2 4表示每2秒採樣一次,共採樣4次

②.詳解

i.vmstat -n x y:表示採樣間隔x(單位:秒),總計採樣y次

ii.-procs

r:運行和等待CPU時間片的進程數,原則上1核CPU的運行隊列不要超過2,整個系統的運行隊列不能超過總核數的2倍,否則代表壓力過大

b:等待資源的進程數,比如正在等待磁盤I/O、網絡I/O等

iii.-cpu

us:用戶進程消耗CPU時間比,us值高,用戶進程消耗CPU時間多,如果長期大於50%,優化程序

sy:內核進程消耗的CPU時間百分比

us + sy參考值爲80%,如果us + sy大於80%,說明可能存在CPU不足

id:處於空閒的CPU百分比

wa:系統等待IO的CPU時間百分比

st:從虛擬機中偷走的百分比(如果正在使用虛擬機話,有此列,虛擬機想運行但是系統管理程序轉而運行其的對象的時間,如果虛擬機不希望運行任何對象,但是系統管理員運行了其他對象,這不算被偷走的cpu時間)

iv.-memory

swpd:虛擬內存已使用的大小,如果大於0,表示你的機器物理內存不足了,如果不是程序內存泄露的原因,那麼你該升級內存了或者把耗內存的任務遷移到其他機器。

free:空閒的物理內存的大小,我的機器內存總共8G,剩餘3415M。

buff:Linux/Unix系統是用來存儲,目錄裏面有什麼內容,權限等的緩存,我本機大概佔用300多M

cache cache:直接用來記憶我們打開的文件,給文件做緩衝,我本機大概佔用300多M(這裏是Linux/Unix的聰明之處,把空閒的物理內存的一部分拿來做文件和目錄的緩存,是爲了提高 程序執行的性能,當程序使用內存時,buffer/cached會很快地被使用。)

v.-swap

si:每秒從磁盤讀入虛擬內存的大小,如果這個值大於0,表示物理內存不夠用或者內存泄露了,要查找耗內存進程解決掉。我的機器內存充裕,一切正常。

so:每秒虛擬內存寫入磁盤的大小,如果這個值大於0,同上。

vi.-io

bi:塊設備每秒接收的塊數量,這裏的塊設備是指系統上所有的磁盤和其他塊設備,默認塊大小是1024byte,我本機上沒什麼IO操作,所以一直是0,但是我曾在處理拷貝大量數據(2-3T)的機器上看過可以達到140000/s,磁盤寫入速度差不多140M每秒

bo:塊設備每秒發送的塊數量,例如我們讀取文件,bo就要大於0。bi和bo一般都要接近0,不然就是IO過於頻繁,需要調整。

vii.-system

in:每秒CPU的中斷次數,包括時間中斷

cs:每秒上下文切換次數,例如我們調用系統函數,就要進行上下文切換,線程的切換,也要進程上下文切換,這個值要越小越好,太大了,要考慮調低線程或者進程的數目,例如在apache和nginx這種web服務器中,我們一般做性能測試時會進行幾千併發甚至幾萬併發的測試,選擇web服務器的進程可以由進程或者線程的峯值一直下調,壓測,直到cs到一個比較小的值,這個進程和線程數就是比較合適的值了。系統調用也是,每次調用系統函數,我們的代碼就會進入內核空間,導致上下文切換,這個是很耗資源,也要儘量避免頻繁調用系統函數。上下文切換次數過多表示你的CPU大部分浪費在上下文切換,導致CPU幹正經事的時間少了,CPU沒有充分利用,是不可取的。

③.額外查看

i.mpstat -P ALL 2:查看所有cpu核信息

pidstat [ 選項 ] [ <時間間隔> ] [ <次數> ]

-u:默認的參數,顯示各個進程的cpu使用統計

-r:顯示各個進程的內存使用統計

-d:顯示各個進程的IO使用情況

-p:指定進程號

-w:顯示每個進程的上下文切換情況

-t:顯示選擇任務的線程的統計信息外的額外信息

-T { TASK | CHILD | ALL }

這個選項指定了pidstat監控的。TASK表示報告獨立的task,CHILD關鍵字表示報告進程下所有線程統計信息。ALL表示報告獨立的task和task下面的所有線程。

注意:task和子線程的全局的統計信息和pidstat選項無關。這些統計信息不會對應到當前的統計間隔,這些統計信息只有在子線程kill或者完成的時候纔會被收集。

-V:版本號

-h:在一行上顯示了所有活動,這樣其他程序可以容易解析。

-I:在SMP環境,表示任務的CPU使用率/內核數量

-l:顯示命令名和所有參數

ii.pidstat -u 1 -p 進程編號:查看單個進程使用cpu的用量分解信息

pidstat [ 選項 ] [ <時間間隔> ] [ <次數> ]

-u:默認的參數,顯示各個進程的cpu使用統計

-r:顯示各個進程的內存使用統計

-d:顯示各個進程的IO使用情況

-p:指定進程號

-w:顯示每個進程的上下文切換情況

-t:顯示選擇任務的線程的統計信息外的額外信息

-T { TASK | CHILD | ALL }

這個選項指定了pidstat監控的。TASK表示報告獨立的task,CHILD關鍵字表示報告進程下所有線程統計信息。ALL表示報告獨立的task和task下面的所有線程。

注意:task和子線程的全局的統計信息和pidstat選項無關。這些統計信息不會對應到當前的統計間隔,這些統計信息只有在子線程kill或者完成的時候纔會被收集。

-V:版本號

-h:在一行上顯示了所有活動,這樣其他程序可以容易解析。

-I:在SMP環境,表示任務的CPU使用率/內核數量

-l:顯示命令名和所有參數

[3].內存:free

①.默認以kb爲單位,可通過參數來調節單位

-b (B), -k (KB), -m (MB), -g (GB) and –tera (TB)

②.經驗:

i.應用程序可用內存/系統物理內存>70%內存充足

ii.應用程序可用內存/系統物理內存<20%內存不足,需要增加內存

iii.20%-70%內存基本夠用

③.相關:pidstat -p 進程號 -r 間隔描述

[4].硬盤:df

df -h:查看磁盤剩餘空間數

[5].磁盤IO:iostat

①.命令iostat [ 選項 ] [ <時間間隔> [ <次數> ]]

②.常用參數

-c:只顯示系統CPU統計信息,即單獨輸出avg-cpu結果,不包括device結果

-d:單獨輸出Device結果,不包括cpu結果

-k/-m:輸出結果以kB/mB爲單位,而不是以扇區數爲單位

-x:輸出更詳細的io設備統計信息

interval/count:每次輸出間隔時間,count表示輸出次數,不帶count表示循環輸出

說明:更多選項使用使用man iostat查看

③.iostat   從系統開機到當前執行時刻的統計信息

輸出含義:

avg-cpu: 總體cpu使用情況統計信息,對於多核cpu,這裏爲所有cpu的平均值。重點關注iowait值,表示CPU用於等待io請求的完成時間。

Device: 各磁盤設備的IO統計信息。各列含義如下:

Device: 以sdX形式顯示的設備名稱

tps: 每秒進程下發的IO讀、寫請求數量

KB_read/s: 每秒從驅動器讀入的數據量,單位爲K。

KB_wrtn/s: 每秒從驅動器寫入的數據量,單位爲K。

KB_read: 讀入數據總量,單位爲K。

KB_wrtn: 寫入數據總量,單位爲K。

④.iostat -xdk 2 3    每隔2S輸出磁盤IO的詳細詳細,總共採樣3次

以上各列的含義如下:

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隊列非空的時間比率,若接近100%說明磁盤帶寬跑滿,需要優化程序或者增加磁盤

⑤.重點關注參數

iowait% 表示CPU等待IO時間佔整個CPU週期的百分比,如果iowait值超過50%,或者明顯大於%system、%user以及%idle,表示IO可能存在問題。

avgqu-sz 表示磁盤IO隊列長度,即IO等待個數。若長期大隊列,也說明IO新能不佳

rkB/s、wkB/s、r/s、w/s若這些值一直處於很高,說明程序一直處於高IO狀態,需要排查分析是否程序需要優化

await若和svctm越接近,表示磁盤IO性能好,反之,若await遠大於svctm則說明IO隊列等待時間過長,需要優化程序或者更換磁盤

%util 表示磁盤忙碌情況,一般該值超過80%表示該磁盤可能處於繁忙狀態。

⑥.相關:pidstat -d 採樣間隔秒數 -p 進程號

[6].網絡IO:ifstat

①.若本地需要安裝

wget http://distfiles.macports.org/ifstat/ifstat-1.1.tar.gz

tar xzvf ifstat-1.1.tar.gz

cd ifstat-1.1

./configure

make

make install

②.命令,ifstat,注意要用安裝的ifstat

③.參數:

-l  監測環路網絡接口。缺省情況下ifstat監測活動的所有非環路網絡接口

-a  監測能檢測到的所有網絡接口的狀態信息。

-z  隱藏流量是無的接口,如接口啓動了但是未使用的。

-i <interface>  指定要監測的接口。

-s 通過SNMP查詢一個遠程主機。

-h 顯示幫助信息

-n 關閉週期性顯示頭部信息。

-t 在每一行的開頭加一個時間戳

-T 報告所有檢測接口的全部帶寬

-w 指定間隔時間(與官方的文檔說明並不同,不知道是不是寫文檔的人寫錯,反正我測試後是間隔時間)

-W 如果顯示內容超出終端窗口的寬度,就換行

-S 在同一行更新顯示內容

-b 用kbits/s顯示帶寬

-q 按鍵模式

-v 顯示版本信息

-d 指定一個驅動來收集狀態信息

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