1. Arthas有什麼功能,怎麼用,請看:Arthas使用手冊
2. Arthas指令比較複雜,一個幫助生成指令的IDEA插件:arthas idea plugin 使用文檔
3. 基于Arthas實作的簡單好用的熱部署插件:ArthasHotSwap
一 引言
首先我們應該抛棄面向debug程式設計的思維,debug不一定是最高效的方法,遇到線上問題不能debug了怎麼辦。本文介紹如何使用Arthas代替debug提高日常開發效率。
開始之前,可以先浏覽下上面推薦的這些文章,下面所使用到的東西在以上的文章都有詳細的講解。大家也可以先浏覽下面的内容,确定所描述的确實可以提高開發效率,再去看上面的文章也是可以的。
首先我們要安裝兩個插件“arthas idea” 和 “ArthasHotSwap”,IDEA可以直接安裝使用。“arthas idea”是為了高效率生成Arthas指令,“ArthasHotSwap”可以實作簡單快捷的熱部署。接下來我們通過幾個場景來看如何使用Arthas提高日開發常效率。
二 5分鐘解決一個問題
1 問題表象
問題的表象是預發接口傳回參數為空,不知道為什麼為空,關鍵地方又沒有打日志。怎麼辦,debug?debug端口不好申請,而且一直占用環境引起公憤。加日志重新部署?部署時間太長,而且不一定檢視日志就能發現問題。接下去我将使用Arthas排查問題。
2 如何發現問題
第一步:定位相關方法
首先定位到相關的代碼,代碼如下圖所示,方法執行結果應該要傳回一個map,也就是上面問題的extraData,傳回為空,肯定是這裡有問題,但不知道那行代碼的問題。借助Arthas可以想到的是,我能觀測這個方法的出參和入參,說不定能發現問題。于是使用Arthas的watch指令觀測方法執行情況。
第二步:生成方法觀測指令
安裝了“arthas idea”插件之後,在方法名上面單擊右鍵,選擇watch,如下圖所示。
第三步:登入應用伺服器
一般應用都部署在雲上或其他遠端伺服器,我們需要登入應用部署的伺服器。
第四步:安裝Arthas
Arthas 支援在 Linux/Unix/Mac 等平台上一鍵安裝,請複制以下内容,并粘貼到指令行中,敲 回車 執行即可。
curl -L https://arthas.aliyun.com/install.sh | sh
第五步:運作Arthas
上述指令會下載下傳啟動腳本檔案 as.sh 到目前目錄,直接在shell下面執行./as.sh,就會進入互動界面。
第六步:執行觀測方法指令
第二步執行完後,觀測方法的指令已經在粘貼闆了,粘貼執行就行,示例指令如下:
watch com.**.**.endpoint.BargainPlayApplyCycleEndPoint fetchPlayDetailRenderData '{params,returnObj,throwExp}' -n 5 -x 3 'params[0].getPlayToolDO().getId()==588'
指令解釋:'{params,returnObj,throwExp}' 表示觀測對象,這裡選擇了入參、出參和異常,-n 5 表示觀測到5次後停止,-x 3 表示列印觀測對象的時候隻列印3層嵌套結構,'params[0].getPlayToolDO().getId()==588' 為條件表達式,滿足該條件的才會被觀測到。
第七步:檢視觀測結果
前端重新觸發執行後,得到觀測結果如下所示,從入參可以看到playActivityApplyRequest中的targetId為null,實際上應該要取playActivityRecordDO中的targetId。從傳回結果可以看到确實是因為商品ID不存在原因。
3 更進一步解決問題
截止目前已經發現了問題所在,一般的同學都是修改代碼重新部署,等上10多分鐘。我們要做不一般的同學,接下去就輪到ArthasHotSwap熱部署插件上場了。在IDEA的插件倉庫搜尋并安裝ArthasHotSwap。
ArthasHotSwap 熱部署
修改代碼 -> maven編譯 -> 單擊右鍵選擇swap this class -> 熱部署指令已經複制到粘貼闆 -> 登入遠端伺服器粘貼并執行熱部署指令 -> 熱部署成功
問題解決
熱部署成功,問題解決,前端重新請求,前端展示正常。
雖然整個鍊路看上去很長,但是都是一些很簡單的複制粘貼操作,這是我在聯調過程中處理的實際問題,整個過程差不多就是5分鐘左右,切身感受到Arthas的便利,忍不住分享一下。
4 一些限制
arthas redefine有一些限制導緻熱部署也有同樣的限制。熱部署時候,不能修改方法名、屬性字段,隻能修改方法體裡面的代碼。
redefine 指令和 jad/watch/trace/monitor/tt 等指令會沖突。執行完 redefine 之後,如果再執行上面提到的指令,則會把 redefine 的位元組碼重置。也就是說,熱部署執行完成之後,再執行 jad/watch/trace/monitor/tt 等指令,會使熱部署失效,是以在适當的時候還是需要重新部署下。我們也可以采用其他方法規避,比如使用watch的時候,觀測其他類的方法,而不是熱部署的那個類。
三 方法執行的時間隧道
上面的場景講到了使用watch指令觀測方法執行參數,但是watch是觀測方法執行瞬間的情況。如果我們想重制上次的調用該怎麼辦呢。
在日常開發過程中,環境問題是非常影響開發效率的,特别是涉及其他團隊的應用的時候,有時候希望上遊再次觸發一次調用都是很困難的一件事情。當你用上面的方法解決了你的問題之後,你想調試一下,發現已經夜深了,不好意思再讓上遊應用觸發一次調用,該怎麼辦呢,自己根據watch觀測的方法入參組裝參數使用hsf控制台調用?我們要做不一般的同學,用工具解放生産力。
1 擷取tt指令
Arthas的tt指令可以擷取方法執行資料的時空隧道,記錄下指定方法每次調用的入參和傳回資訊,并能對這些不同的時間下調用進行觀測。
安裝好arthas idea插件之後,在需要記錄執行的方法上面單擊右鍵,選擇TimeTunnel Tt,出現下面的選擇框,第一個紅框是擷取記錄方法執行的指令。第二個紅框是記錄方法執行之後需要對記錄進行的操作,包括檢視記錄清單、檢視記錄執行情況、重制調用等。
2 記錄方法執行
登入遠端伺服器,運作以下兩條運作arthas,然後執行從idea插件複制的tt -t指令來記錄方法執行,如下圖所示。如果想停止記錄可以輸入q,檢視記錄使用tt -l。
curl -L https://arthas.aliyun.com/install.sh | sh
./as.sh
3 搜尋方法執行記錄
tt -l可以檢視所有的方法執行記錄,但是我們要和我們相關的執行記錄,那麼可以使用tt -s指令進行搜尋。tt -s 指令後面需要攜帶過濾條件。條件表達式是使用OGNL編寫,下面介紹幾個通常的過濾表達式。首先介紹下幾個對象,params表示入參,params[0]表示第一個參數,params[1]表示第二個參數,returnObj表示傳回對象。
- 根據入參過濾:tt -s 'params[2].getRecordId() == 110213603'
- 根據傳回結果過濾:tt -s 'returnObj.isSuccess() == false'
- 根據入參和傳回結果過濾:tt -s 'returnObj.isSuccess() == true && params[2].getRecordId() == 110213603'
4 檢視方法執行情況
tt -w 相當于tt下面的watch指令,可以用來檢視方法執行情況。使用idea插件擷取tt -w 指令更友善。
5 重新觸發
如果需要重新觸發某條記錄也是可行的,因為tt指令記錄當時調用的情況,是以可以本地發起一次調用,tt -p -i 1000 指令的意思重新觸發idex=1000的那條記錄。不僅僅可以重新觸發,還可以間隔時間内多次觸發,tt -p --replay-times 5 --replay-interval 2000 -i 1000 表示重新觸發5次,每次間隔2s。
重新觸發的時候我們可能還想再watch下方法執行情況,怎麼辦呢,另外再打開一個頁面登入遠端伺服器,運作arthas,執行 watch 指令。
6 一些限制
ThreadLocal 資訊丢失
很多架構偷偷的将一些環境變量資訊塞到了發起調用線程的 ThreadLocal 中,由于調用線程發生了變化,這些 ThreadLocal 線程資訊無法通過 Arthas 儲存,是以這些資訊将會丢失。一些常見的 CASE 比如:鷹眼的 TraceId 等。
引用的對象
需要強調的是,tt 指令是将目前環境的對象引用儲存起來,但僅僅也隻能儲存一個引用而已。如果方法内部對入參進行了變更,或者傳回的對象經過了後續的處理,那麼在 tt 檢視的時候将無法看到當時最準确的值。這也是為什麼 watch 指令存在的意義。
作者:默達
來源-微信公衆号:阿裡雲開發者
出處:https://mp.weixin.qq.com/s/UAO5qHvO6VIhvyCSZnW--g