arthas使用介紹

背景:

一次線上問題的綜合排查排查,兩個相同的系統的某個模塊,數據量更少的系統查詢更慢。
先說下總體思路:java

  1. 查看系統整理負載,網絡有100左右毫秒的延遲,看起來影響不大
  2. 查看正序運行總體狀況,一次查詢會經歷3次FGC,有問題,解決後雖然會快一些可是仍是有點慢
  3. 跟蹤調用棧,發現有點在獲查詢結果的時候特別慢
  4. 排查是否有mysql慢查詢(定義爲1秒以上的查詢),結果是沒有
  5. 經過arthas發現調用了20屢次查詢,每次網絡延遲100ms,加起來就有2s了,定位出問題。

這樣看起來arthas真的很強大,它不只僅能處理上述問題,還能....mysql

  • 這個類從哪一個 jar 包加載的?爲何會報各類類相關的 Exception?
  • 我改的代碼爲何沒有執行到?難道是我沒 commit?分支搞錯了?
  • 遇到問題沒法在線上 debug,難道只能經過加日誌再從新發布嗎?
  • 線上遇到某個用戶的數據處理有問題,但線上一樣沒法 debug,線下沒法重現!
  • 是否有一個全局視角來查看系統的運行情況?
  • 有什麼辦法能夠監控到JVM的實時運行狀態?
  • 代碼出現異常,怎麼能獲取請求參數和返回值。

Arthas究竟是什麼

Arthas 是Alibaba開源的Java診斷工具,採用命令行交互模式,提供了豐富的功能,是排查jvm相關問題的利器。
在逛github時,發現了這款利器,深刻了解以後,簡直驚爲天人。下面先列舉一下它能作的一些事情:git

  • 提供性能看板,包括線程、cpu、內存等信息,而且會定時的刷新。
  • 根據各類條件查看線程快照。好比找出cpu佔用率最高的n個線程等
  • 輸出jvm的各類信息,如gc算法、jdk版本、ClassPath等
  • 查看/設置sysprop和sysenv
  • 查看某個類的靜態屬性,也能夠經過ognl語法執行一些語句
  • 查看已加載的類的詳細信息,好比這個類從哪一個jar包加載的。也能夠查看類的方法的信息
  • dump某個類的字節碼到指定目錄
  • 直接反編譯指定的類
  • 查看類加載器的一些信息
  • 可讓jvm從新加載某個類
  • 監控方法的執行,同時能夠獲取到執行的入參、出參以及拋出的異常
  • 追蹤方法執行的調用棧,以及各個方法的調用時間

Arthas運行原理

image

Arthas命令列表

image

athas的各個命令

sc 和 sm

  • 經過sc能夠查看已加載類的相關信息,好比該類是從哪一個jar包加載的,被哪一個類加載器加載的,以及是不是接口等等。
  • sm查看已加載類的方法詳情。

dashboard

進入當前系統的實時數據面板,按 ctrl+c 退出。這個面板會實時刷新,其中包括線程信息、內存信息、gc信息、還有一些運行時的數據。
另外,當運行在Ali-tomcat時,會顯示當前tomcat的實時信息,如HTTP請求的qps, rt, 錯誤數, 線程池信息等等。github

image

thread

經過thread命令能夠查看當前jvm進程的線程詳情。能夠查看線程的cpu使用時間佔比,經過指定各類參數能夠找出最忙的幾個線程,以及阻塞其餘線程的線程。具體如何使用這裏很少作介紹,你們能夠去看arthas的官方文檔。正則表達式

當前最忙的前N個線程並打印堆棧
thread -i 5000 
thread -i 5000

image

jvm

經過jvm命令直接輸出當前jvm的各類信息。算法

getstatic

經過getstatic命令能夠方便的查看類的靜態屬性。sql

getstatic demo.MahtGame random

image

sysprop和sysenv

  • 經過sysprop能夠查看全部的系統變量,也能夠設置某個系統變量。
  • 同理,經過sysenv能夠查看全部的操做系統環境變量,也能夠查看設置某個環境變量。

ognl

執行ognl表達式,可執行任意代碼express

Ognl @demo.MathGame@random

image

動態修改日誌級別apache

  1. 經過ognl獲取對應類上的logger對象實現類
  2. sc命令來查看具體從哪一個jar包里加載的,sc -d org.apache.log4j.Logger
  3. 經過ognl修改日誌級別

image

更詳細的介紹:https://github.com/alibaba/arthas/issues/11vim

dump

將已加載類的字節碼dump到本地磁盤上。

jad

有時咱們常常會不肯定線上或者測試環境的包是不是咱們修改過的,這時候就能夠經過jad反編譯來看下。

反編譯指定已加載類的源碼,jad demo.MathGame

image

classloader

將 JVM 中全部的classloader的信息統計出來,並能夠展現繼承樹,urls等。

redafine

該命令能夠加載外部的.class文件,而後覆蓋 jvm已加載的類。注意,這個命令不必定都能覆蓋成功,若是添加了新的field,就不會加載成功。

關於redefine,arthas的github上有個很是經典的userCase:

https://github.com/alibaba/arthas/issues/263

動態更新代碼,不用重啓jvm

image

watch

  • 讓你能方便的觀察到指定方法的調用狀況。能觀察到的範圍爲:返回值、拋出異常、入參,經過編寫 OGNL 表達式進行對應變量的查看。
  • watch的使用姿式比較豐富,能夠在四個不一樣的場景觀察方法的執行。好比方法調用以前、方法調用以後、方法異常以後、方法結束以後。默認觀察的是方法結束以後。
  • 若是觀察的是方法結束以後的場景,因爲入參可能在執行方法時被改變,因此此時輸出的可能不是真正的入參。所以,要看真正的入參,要看方法調用以前的,也就是加上-b的參數。
  • 另外,使用-b參數觀察的話,則觀察不到方法返回的結果以及拋出的異常了。
參數名稱 參數說明
class-pattern 類名錶達式匹配
method-pattern 方法名錶達式匹配
express 觀察表達式
condition-express 條件表達式
[b] 在方法調用以前觀察
[e] 在方法異常以後觀察
[s] 在方法返回以後觀察
[f] 在方法結束以後(正常返回和異常返回)觀察
[E] 開啓正則表達式匹配,默認爲通配符匹配
[x:] 指定輸出結果的屬性遍歷深度,默認爲 1
[n:] 只執行n次,默認會不斷輸出,除非用戶按下cltr+c
# 觀察CommonTest的test方法
# 輸出 入參、返回結果、拋出的異常 —— 輸出的內容能夠動態調整
# 後面跟着的是 條件表達式,表示耗時超過10ms才輸出
# -n 表示只執行一次,-x表示 入參和返回結果的展開層次爲5層
watch *.CommonTest test "{params,returnObj,throwExp}" '#cost>10' -x 5 -n 1

# 耗時大於10ms而且第一個參數等於1才輸出
watch *.CommonTest test "{params,returnObj,throwExp}" '#cost>10 && params[0]==1' -x 5 -n 1
# 第一個參數大於1 而且第二個參數等於hello才輸出
watch *.CommonTest test "{params,returnObj,throwExp}" 'params[0]>1 && params[1]=="hello"' -x 5 -n 1
# 第一個參數小於5或者第二個參數等於"world"就輸出
watch *.CommonTest test "{params,returnObj,throwExp}" 'params[0]<5 || params[1]=="wolrd"' -x 5 -n 1
# 第一個參數的name字段等於world時才輸出。
# 因爲在方法執行過程當中參數的name屬性可能發生改變,所以加上-b才能觀察到真正的入參
watch -b *.CommonTest test "{params,returnObj,throwExp}" 'params[0].name=="wolrd"' -x 5 -n 1

# 因爲同時指定了-s和-b,因此方法被調用一次,就會輸出2次結果(兩個場景分開輸出),分別是方法被調用前,和返回以後
# 注意,這裏若是-n只設置成1,那麼只會輸出-b對應的輸出,-s對應的輸出因爲沒有次數了就沒法輸出了
watch *.CommonTest test '{params,returnObj,throwExp}' -x 5 -n 2 -s -b

在填寫條件表達式時要注意一點,條件表達式中的params默認都是獲取的方法執行完後的參數信息,好比入參a的屬性name方法執行前是"hello",在方法執行後變成了"world",那麼條件表達式傳入'params[0].name="hello"'將不會輸出,只有填入'params[0].name="hello"'才能夠匹配上。這點對於後面的trace、stack命令也是同樣的。

查看方法輸入參數/返回值/異常信息,watch demo.MathGame primeFactors "{params,returnObj}" -x 2
image

monitor

monitor命令能夠監控方法的執行狀況。好比調用成功次數,失敗次數,失敗率、平均執行時間等等。默認120秒輸出一次,也就是說,當咱們輸入monitor命令以後,每120秒就會輸出一次統計結果。

經過-c參數能夠修改輸出頻率,支持通配符和正則表達式。
monitor -c 5 demo.MathGame primeFactors
image

trace

方法內部調用路徑,並輸出方法路徑上的每一個節點上耗時,tt命令會記錄每次方法調用的各類信息。它和watch有些類似可是它能記錄下各個時間點的調用信息,以後隨時查看,甚至replay此次調用。

trace demo.MathGame run

image

tt

timetunnel,記錄下指定方法每次調用的入參和返回信息,並能對這些不一樣的時間下調用進行觀測,同時可回放該方法調用
tt -t demo.MathGame primeFactors

image

直接重放請求參數

1.使用tt –t 類名次 方法名次
2.tt –play -i 1000

另外介紹幾個我常常用的工具,jmap,jstat,jstack,dump這些基本的就不介紹了。

Tprofiler

TProfiler是一個能夠在生產環境長期使用的性能分析工具.它同時支持剖析和採樣兩種方式,記錄方法執行的時間和次數,生成方法熱點 對象建立熱點 線程狀態分析等數據,爲查找系統性能瓶頸提供數據支持.

TProfiler在JVM啓動時把時間採集程序注入到字節碼中,整個過程無需修改應用源碼.運行時會把數據寫到日誌文件,通常狀況下每小時輸出的日誌小於50M.

show-busy-java-threads

  • 查找cpu性能消耗過程
    top命令找出消耗CPU高的Java進程及其線程id:
    開啓線程顯示模式(top -H,或是打開top後按H)
    按CPU使用率排序(top缺省是按CPU使用降序,已經合要求;打開top後按P能夠顯式指定按CPU使用降序)
    記下Java進程id及其CPU高的線程id
  • 查看消耗CPU高的線程棧:
    用進程id做爲參數,jstack出有問題的Java進程
    手動轉換線程id成十六進制(能夠用printf %x 1234)
    在jstack輸出中查找十六進制的線程id(能夠用vim的查找功能/0x1234,或是grep 0x1234 -A 20)
  • 查看對應的線程棧,分析問題
    查問題時,會要屢次上面的操做以分析肯定問題,這個過程太繁瑣太慢了。

參考:https://blog.csdn.net/u013332124/article/details/84888074#11_redefine_157

相關文章
相關標籤/搜索