如何在生產環境使用Btrace進行調試

轉載地址:http://www.importnew.com/23614.html

背景

記得前幾天有人問我:在生產環境中可能經常遇到各種問題,你們一般是如何進行調試的? 很慚愧,沒有經驗。因爲平時碰不到生產環境的服務器,定位問題需要各種數據,所以大多數問題的解決方式都是在本地打斷點進行調試,或者在測試環境利用輸出日誌進行調試,這種方式簡單粗暴,但過程比較繁瑣,需要各種重新發布,重啓應用,還不能保證一次就找到問題的根源。直到最近才瞭解到Btrace這個工具,對於這樣一個神器,我覺得有必要記錄一篇,讓更多的人知道。

Btrace

BTrace是sun公司推出的一款Java 動態、安全追蹤(監控)工具,可以在不用重啓的情況下監控系統運行情況,方便的獲取程序運行時的數據信息,如方法參數、返回值、全局變量和堆棧信息等,並且做到最少的侵入,佔用最少的系統資源。

項目地址:Btrace
用戶指南:UserGuide

由於Btrace會把腳本邏輯直接侵入到運行的代碼中,所以在使用上做很多限制:
1、不能創建對象
2、不能使用數組
3、不能拋出或捕獲異常
4、不能使用循環
5、不能使用synchronized關鍵字
6、屬性和方法必須使用static修飾

根據官方聲明,不恰當的使用BTrace可能導致JVM崩潰,如在BTrace腳本使用錯誤的class文件,所以在上生產環境之前,務必在本地充分的驗證腳本的正確性。

Btrace可以做什麼?

1、接口性能變慢,分析每個方法的耗時情況;
2、當在Map中插入大量數據,分析其擴容情況;
3、分析哪個方法調用了System.gc(),調用棧如何;
4、執行某個方法拋出異常時,分析運行時參數;
5、….

Btrace第一個例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package com.metty.rpc.common;
import java.util.Random;
 
/**
 * Created by j_zhan on 2016/11/28.
 */
public class BtraceCase {
    public static Random random = new Random();
    public int size;
 
    public static void main(String[] args) throws Exception {
        new BtraceCase().run();
    }
 
    public void run() throws Exception {
        while (true) {
            add(random.nextInt(10), random.nextInt(10));
        }
    }
 
    public int add(int a, int b) throws Exception {
        Thread.sleep(random.nextInt(10) * 100);
        return a + b;
    }
}

執行add方法時,對傳入參數、返回值以及執行耗時進行分析,btrace腳本:

通過jps命令獲取pid爲8454
執行btrace 8454 Debug.java實現對運行代碼的監控,輸出結果如下:

可以發現,Btrace可以獲取每次執行add方法時的數據,當然Btrace能做的遠遠不止這些,比如獲取當前jvm堆使用情況、當前線程的執行棧等等。

參數說明

@OnMethod

Btrace使用@OnMethod註解定義需要分析的方法入口

在@OnMethod註解中,需要指定class、method以及location等,class表明需要監控的類,method表明需要監控的方法,指定方式如下:
1、使用全限定名:clazz="com.metty.rpc.common.BtraceCase", method="add"
2、使用正則表達式:clazz="/javax\.swing\..*/", method="/.*/"
3、使用接口:clazz="+com.ctrip.demo.Filter", method="doFilter"
4、使用註解:clazz="@javax.jws.WebService", method=""@javax.jws.WebMethod"
5、如果需要分析構造方法,需要指定method="<init>"

@Location

定義Btrace對方法的攔截位置,通過@Location註解指定,默認爲Kind.ENTRY
1、Kind.ENTRY:在進入方法時,調用Btrace腳本
2、Kind.RETURN:方法執行完時,調用Btrace腳本,只有把攔截位置定義爲Kind.RETURN,才能獲取方法的返回結果@Return和執行時間@Duration

3、Kind.CALL:分析方法中調用其它方法的執行情況,比如在execute方法中,想獲取add方法的執行耗時,必須把where設置成Where.AFTER

4、Kind.LINE:通過設置line,可以監控代碼是否執行到指定的位置

5、Kind.ERROR, Kind.THROW, Kind.CATCH
用於對某些異常情況的跟蹤,包括異常拋出,異常被捕獲,異常未捕獲被拋出方法之外

如何使用Btrace定位問題

1、找出所有耗時超過1ms的過濾器Filter

由於@Dutation返回的時間是納秒級別,需要進行轉換,如果定位一個Filter性能變慢,接着使用@Location(Kind.CALL)進行更細粒度的分析。

2、分析哪個方法調用了System.gc(),調用棧如何?

通過查看調用棧,可以很清楚的發現哪個類哪個方法調用了System.gc()

3、統計方法的調用次數,且每隔1分鐘打印調用次數

Btrace的@OnTimer註解可以實現定時執行腳本中的一個方法

4、方法執行時,查看對象的實例屬性值

通過反射機制,可以很方法的得到當前實例的屬性值

總結

Btrace能做的事情太多,但使用之前切記檢查腳本的可行性,一旦Btrace腳本侵入到系統中,只有通過重啓才能恢復。


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