應用系統性能問題
- 進程消耗cpu,內存利用率暴增如何定位代碼
- 數據庫連接數被耗盡怎麼辦
- 各種OOM如何預防
- 線程死鎖,鎖爭用
- 上下文切換太頻繁那怎麼辦
無論多複雜的系統運行在linux上,其實就是一個進程,任何東西在操作系統層面都是以文件的形式存儲的,進程也不例外,所以從操作系統的層面只需要關注進程和線程即可
linux上部署一個Tomcat的程序,產生的是一個進程,這個進程所有的東西就會在如下圖的一個目錄proc/pid下
ll /proc/15208
# 通過ps -ef找到對應的進程id
我們所關注的日常日誌輸出在哪裏,系統加載哪些jar包,系統啓動的時候是哪個java版本等等這些問題都會在這張圖中找到答案,在複雜的微服務中快速地需要找到這些信息的情況
ll /proc/29242/fd | grpe socket | head -n 20
# head命令可以取出文件的前面幾行,語法爲:
head [-n number] 文件
還需要找到系統和哪些外部應用在交互,包括使用的哪些中間件服務,比如Elasticsearch、Redis、mq等,這些都可以通過socket的端口能夠找到,因爲應用底層所有的通信都是通過socket
系統畫像的緯度
性能關注維度
一般來說,業務系統系統性能主要關注兩件事,一個是吞吐量,一個是系統的響應性
一、CPU
如果cpu的利用率不高,但是系統的吞吐量和響應性卻不理想,這時候說明程序並沒有忙於計算,可能問題出現在IO上
二、IO
IO和CPU的利用率一般是呈反比,CPU利用率高則IO不大
關於IO,一個是磁盤IO,一個是驅動程序的IO,一個是內存換頁率
三、網絡帶寬
如果CPU利用率不高、IO利用率不高、內存的使用不高、網絡帶寬使用也不高,但是系統的性能還是上不去,那麼程序一定是被阻塞了,可能是因爲CPU在等待哪個鎖,也可能是因爲某個資源比如接口返回,連接在等待(包括上下文的切換)等
影響應用程序的因素
一、磁盤IO
內存、CPU、IO處理速度對比
CPU看成一個時鐘週期1秒
一級緩存讀取信息好像在桌子上拿起一張紙,比如3秒
二級緩存讀取信息則是從身邊的書架上取出一本書,可能需要14秒
從主從中讀取相當於走到辦公樓下面買個零食,需要4分鐘
從磁盤中尋道的時間相當於離開辦公大樓,並開始長達一年零三個月的環球旅遊
可以看出CPU、內存、IO、硬盤的速度比較
二、網絡IO
某些場景下,由於網絡環境的不確定性,尤其是互聯網上的數據讀寫,網絡操作的速度可能比本地的IO要更慢
三、CPU
CPU的資源爭奪,將導致性能問題,主要是鎖競爭,鎖競爭會導致上下文切換頻繁,帶來嚴重的系統開銷,表現就是內核態的CPU利用率偏高
四、內存
內存做爲系統性能指標之一,最大的可能是內存不足,但是對於java程序只需要關注GC情況
五、連接
系統對外部依賴的中間件和接口,比如說數據庫連接,如果數據量過大或者連接超時,都是比較消耗性能
六、異常
java異常的捕獲和處理非常消耗資源,如果程序高頻率地在異常處理,也會影響系統的性能
快速診斷
一、資源診斷
CPU、IO、內存、磁盤、網絡
- top命令
最需要關注的是top的load average,顯示的是說最近1分鐘、5分鐘和15分鐘之內系統的平均負載。系統的平均負載被定義爲在特定的時間間隔內,運行隊列中(即CPU上運行或者等待運行多個進程的平均進程數)。比如現在系統有兩個正在運行的進程,三個可運行的進程,那麼系統的load就是5。CPU核數和Load Average的關係好比高速公路上的多車道,如果車輛過多就會顯示擁擠,故load average越高說明系統的性能越差
如果CPU處理的進程數大於5,那這時候性能就比較嚴重。假如CPU是8核,過去1分鐘、5分鐘和15分鐘的load
average的值爲60.58、61.14、61.22,可以計算出平均每核的數據
另外,我們需要關注用戶態的CPU和內核態的CPU,也就是us和sy的數值
-
內存問題
如果需要查看某個進程,佔用的物理內存和虛擬內存,可以直接使用命令pidstat - r -p pid 1 2來定位
如果要查看某個進程文件的IO情況,可以通過命令pidstat加參數去查看
Vmstat命令中swpd過高,通常是物理內存不夠用了,swap的消耗主要關注它的IO,如果IO發生比較頻繁,那麼也會影響系統的性能 -
網絡問題
trace命令可以用來跟蹤進程的執行和系統的調用,通過trace -T之間的參數,可以顯示具體的進程系統調用的情況
網絡的IO也可以通過cat proc interrupts來查看,網絡IO消耗需要關注網卡中斷,是否不均衡分配到各個CPU -
磁盤問題
一般使用dstat來查看
二、連接
應用往往需要和外部的服務交互,比如數據庫、緩存
通過netstat的命令可以查看,可以發現系統正在和哪些外部的應用交互
netstat -anop|grep 3306
3306的端口(數據庫的連接端口)顯示系統有連接mysql的數據庫,並且有40個連接
有時候會報錯has already more than最大的連接數,這時候用此命令查看連接數的數量,當連接數非常多的時候,最大的可能是代碼在不停地操作數據庫,或者有慢SQL導致的連接不釋放。當應用連接數大於正常連接數時,需要排查系統代碼數據庫操作的問題
三、線程異常
線程異常問題排查
四、TCP狀態診斷
客戶端和服務端TCP建立連接和釋放連接的過程,如下圖
需要重點關注的是CLOSE-WAIT和TIME-WAIT,TIME-WAIT表示主動關閉,CLOSE-WAIT則表示被動關閉。如果客戶端併發量很高,就會出現TIME-WAIT很高,有可能是客戶端的連接連不上,可以通過netstat命令來查詢定位
五、CPU過載診斷
如何定位代碼中哪段導致CPU過載?
cpu過載問題排查
六、OOM
OOM問題排查
七、JVM GC的問題
JVM有很多工具和命令,不過主要需要關注GC的情況。GC會導致系統應用暫時的停頓,如果頻繁的GC就會產生系統延遲響應。開啓GC日誌,可以收集GC的統計和信息,方便觀察和定位應用停頓的原因,也可以通過命令jstat收集相關信息
jstat -gccause 1 1000
八、日誌診斷
檢查日誌異常、Error等各種數據庫異常等,可以快速地瞭解系統地運行情況