Linux環境下使用Arthas定位cpu飆高問題


Linux環境下使用Arthas(阿爾薩斯)定位cpu飆高問題

  • 生產環境cpu飆高的原因
  • Arthas工具如何排查Linux環境下cpu飆高的問題
  • jvisualvm工具如何排查linux環境下cpu飆高的問題(需要做個配置,才能做遠程連接)
  • 生產環境下內存泄露產生的原因
  • Arthas工具如何排查Linux環境下內存泄露的問題

生產環境cpu飆高的原因

cpu上運行的是線程
產生原因:

  1. CAS自旋,沒有控制自旋次數(synchronized鎖:就是使用的自旋,但是如果一直沒有獲取到鎖的話,就會將當前線程從運行狀態變為阻塞狀態) CAS修改值內容,但是CAS也有缺點,就是如果CAS修改值失敗的話,會不斷的進行重試,重試的過程一直是運行狀態的,並且重試是通過循環來實現的,所以是非常消耗cpu資源的
    • 解決方案,如果我們在使用樂觀鎖的時候,要限制重試的次數,不要一直重試
  2. 雲服務器上安裝Redis,黑客攻擊6379端口號,注入挖礦程序
    • Redis端口不要外網訪問
  3. 並發量比較大,或者惡意攻擊
    • 解決方式:限流
  4. 服務器端被DDOS攻擊
    • 其實攻擊不好處理,一般是使用限流,ip黑名單,圖形驗證碼,防止機器模擬攻擊
  5. 死循環
    • 一定要加上循環結束條件

創建線程過程中,要配置線程名稱:阿里巴巴開發手冊中有相應規定,便於排查是那些業務相關問題

在Windows下排查的話,主要是查看任務管理下的進程,根據進程定位到業務相關,如果是找不到業務相關,則表示你的線程命名不規范

在Linux下,可以使用top -c查看那個進程的cpu占比比較高
cpu問題查看

在Windows下,可以使用jdk自帶的jvisualvm排查cpu,但是在1.8之后就沒這個組件了,需要單獨下載jvisualvm獨立版下載

查看cpu占比
java代碼
如果沒有配置線程名稱,則該線程可能為Thread-n,從而無法定位業務問題,所以在開啟線程的時候,一定要定義線程名稱、

實際上jvisualvm也是可以連接遠程的,但是鏈接遠程比較麻煩

linux下排查cpu占比

新建java文件,如Test04.java

public class Test04 {
    public static void main(String[] args) {
        new Thread(() -> {
            while (true) {
                System.out.println("1111111");
            }
        }, "hahaha").start();

    }
}

上傳至linux或者在linux中新建Test04.java,將代碼進行復制
如圖所示
java代碼
之后通過javac命令對其進行編譯

javac Test04.java

得到class文件
就會得到class文件,之后使用java Test04執行該文件,不要加.class,如果是一個jar包的話,則應該是java -jar 項目.jar

如何排查cpu飆高的問題呢,需要使用到arthas,首先下載
阿里雲下載

curl -O https://arthas.aliyun.com/arthas-boot.jar

jar包
如果執行使用以下命令運行的話,會報錯,錯誤原因在於當前服務器沒有一個關於JVM的進程,沒有的話就會報錯,也就是想要使用Arthas的話,必須先要啟動一個關於JVM的進程,因為沒有找到的話,是不能做監控的,所以需要先運行java程序

java -jar arthas-boot.jar

沒有jvm進程的提示
這個時候如果先運行Test04這個class,再次執行Arthas啟動命令,就又會有提示
進程提示
通過top -c查看進程
對應進程
因為有時候可能會檢測到多個,這個時候僅僅只有一個[1],所以可以使用1來代替這個進程,之后回車
輸入進行編號
結果顯示
這個時候就會對這個4501這個進程做監控了,如何查看當前進程的哪個線程占cpu比較高呢,就可以使用以下命令

# 查看當前進程中前3個占用cpu比較高的線程
thread -n 3

cpu占比

一般大型公司都會搭建監控系統,去監控機器,如果cpu飆高,則會發送郵件通知,一般千萬不要超過90%,超過就掛掉了,掛掉就不能排查了
一般是根據一些征兆去提前告警的

如果是docker或者k8s的話,進入容器安裝即可
docker環境

docker exec -it  ${containerId} /bin/bash -c "wget https://arthas.aliyun.com/arthas-boot.jar && java -jar arthas-boot.jar"

k8s環境

kubectl exec -it ${pod} --container ${containerId} -- /bin/bash -c "wget https://arthas.aliyun.com/arthas-boot.jar && java -jar arthas-boot.jar"

查看dashboard

dashboard

通過thread命令來獲取到math-game進程的Main Class

# 會打印線程ID 1的棧,通常是main函數的線程
thread 1 | grep 'main('
    at demo.MathGame.main(MathGame.java:17)

通過jad來反編譯Main Class

jad demo.MathGame

相關教程


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM