JAVA線上程序CPU過高分析

JAVA線上程序CPU過高分析

分析工具atop

atop的安裝
yum install atop -y(centos)
apt-get install atop -y  (ubuntu)
啓動atop

腳本管理

/etc/init.d/atop

配置文件位置及詳情

#位置
/etc/sysconfig/atop

#詳情
# sysconfig atop
# Current Day format(格式化)
CURDAY=`date +%Y%m%d`
# Log files path(輸出日誌到此文件)
LOGPATH=/var/log/atop
# Binaries path(二進制文件)
BINPATH=/usr/bin
# PID File(PID文件)
PIDFILE=/var/run/atop.pid
# interval (default 10 minutes)(默認600s採集一次)
LOGINTERVAL=600

常用命令

c 按照進程cpu使用率進行降序篩選

m按照進程內存使用率進行降序篩選

d 按照進程磁盤使用率進行降序篩選

a 按照進程資源綜合使用率進行降序篩選

n 按照進程網絡使用率進行降序篩選(需要額外安裝內核模塊才支持,默認不支持)

t 跳轉到下一個監控採集點

T 跳轉到上一個監控採集點

B 指定時間點,格式 hh:mm:ss

atop的基礎講解

  1. 基礎面板的講解
    在這裏插入圖片描述
  2. m模式-內存狀態的分析
    在這裏插入圖片描述
  3. d模式-磁盤狀態分析
    在這裏插入圖片描述
  4. p模式-進程狀態模式分析
    在這裏插入圖片描述
  5. 標準/用戶/線程狀態分析
    在這裏插入圖片描述

分析工具top

基礎操作
在這裏插入圖片描述

問題排查

首先你需要知道那個項目有問題,或者通過top/atop知道那個進程佔用較高的cpu

 - 觀察進程中線程的cpu佔用情況
  方法1. 可用通過top -Hp [指定PID]
  方法2. 也可以通過top -p [指定PID] 然後在按shift + h 開啓線程顯示
 - 進行線程堆棧分析
  1. 記錄剛剛顯示的線程中佔用cpu較高的線程id(TID)
  2. 使用printf "%x\n" [指定TID(剛剛佔用較高的線程id)]    將線程對應PID轉爲 16進制數
  3. jstack PID | grep -A 30 "nid=0x + TID16" :查看該線程的堆棧信息
     - 小講解grep -A 30:表示 除匹配到的該行外額外顯示(After)改行之後的30行
     - 小講解grep -B 30:表示 除匹配到的該行外額外顯示(Before)改行之前的30行
     - 小講解grep  30:表示 除匹配到的該行外額外顯示(Before)改行之前和之後的各30行
  4. 通過線程的堆棧信息,定位到CPU佔用過高的代碼,分析其原因
  	 - 常可以結合jstat來分析JVM中的內存信息;(如jstat -gcutil PID 1000 10 、jstat -gc PID 1000 10、jstat -gccause PID 1000 10)
  	 - jmap -heap PID來查看整個JVM內存狀態 ;(要注意的是在使用CMS GC情況下,jmap -heap的執行有可能會導致JAVA進程掛起)
  	 - jmap -histo PID 查看JVM堆中對象詳細佔用情況;
  	 - jmap -dump:format=b,file=文件名 [pid]導出整個JVM中內存信息。

常見服務器CPU過高的問題原因和對應解決方案:
此處引用
[WangCw的夏天]https://blog.csdn.net/qq_33404395/article/details/86242263

  1. 方法中存在讀寫文件流的操作,高併發時每個請求產生一個文件流,導致系統CPU急增。

    • 解決方案:
    • 從線程棧日誌信息中,找出導致CPU高的線程方法。讀寫文件流操作移出方法中,避免每次請求都產生一個文件流。
  2. 方法中使用了多線程,未使用連接池或使用了Executors.newCachedThreadPool()創建的接連池,高併發時創建出過多的後臺線程。

    • 解決方案:
    • 使用jstack命令統計出線程數量;
    • 找出程序中創建線程代碼;
    • 使用Executors.newFixedThreadPool(thread_size)創建固定數量的線程池(線程數固定,無法無收),或者使用new ThreadPoolExecutor(coreSize, maxSize, 60L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue())直接構造線程池。
  3. 發現是gc線程導致的CPU問題比較費時

    • 解決方案:
    • 查看一下gc策略是否合理;
    • 用命令jmap -histo [PID] 分析是哪個類佔用內存比較多,分析出可能存在內存泄露的地方;
    • jvm內存調優,可使用Jconsole、visalvm、probe等工具查看java虛擬機中方法區、堆區(新生代、倖存代、老年代)、線程棧的內存分配,根據實際情況進行優化。
  4. 代碼中存在死循環、死鎖

    • 解決方案:
    • 直接通過jstack獲取到出問題的線程的堆棧信息,分析代碼邏輯。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章