利用Arthas定位線上問題例項
阿新 • • 發佈:2019-10-26
前言
Arthas是一個類似於Btrace的JVM線上除錯分析工具,具體可參考我之前寫的一篇部落格:利用JVM線上除錯工具排查線上問題。本文分享筆者剛遇到的一個問題,雖然不復雜,但是很典型。
問題與分析過程
昨天上線遇到一個問題,交易後給大資料平臺非同步送數,但是他們說沒收到資料,因為我們沒有打日誌,所以沒有直接的證據證明是他們的問題而不是我們的問題。
送數的原理大致如下,就是交易主執行緒把資料放到佇列裡,然後非同步執行緒從佇列裡把資料取出來,傳送到後臺。
佇列: BlockingQueue<Message> queue = new BlockingQueue(); 同步執行緒: void sendMsg(Message msg) { queue.offer(msg); } 非同步執行緒: void consume() { Message msg = queue.take(); while(msg != null) { HttpClient.post(msg); msg = queue.take(); } }
具體送數的程式碼如下( 加了行數):
38 public void consume(Map msg) { 39 HttpClient httpClient = new HttpClient(cm); 40 PostMethod method = new PostMethod(uri); 41 method.addRequestHeader("context-type", "application/x-www-form-urlencoded"); 42 JSONObject json = new JSONObject(msg); 43 NameValuePair[] params = new NameValuePair[2]; 44 params[0] = new NameValuePair("topic", topic); 45 params[1] = new NameValuePair("value", json.toJSONString()); 46 //System.out.println(msg.toString()); 47 logger.info("BigDataHttp Send Json:" + json.toJSONString()); 48 method.addParameters(params); 49 try { 50 51 httpClient.executeMethod(method); 52 if(method.getStatusCode() == 200) { 53 logger.info("BigDataHttp response(Success):"+ method.getResponseBodyAsString()); 54 } else { 55 logger.info("BigDataHttp Response(error):" + method.getResponseBodyAsString()); 56 } 57 } catch(Exception e) { 58 logger.error(e.getMessage(), e); 59 } finally { 60 method.releaseConnection(); 61 } 62 }
在日誌裡沒有發現try裡的異常,而比較遺憾的是,我們的日誌雖然開了info級別,但是因為日誌量太大,所以只開了交易上送和下發報文的日誌,其他的日誌都關了。
現在日誌級別沒法調,有沒有辦法能確定,請求返回了200,還是其他值呢?
可以用線上除錯工具Arthas,我們使用Arthas的trace功能,檢視這個類執行的詳細步驟。
首先連線上這個JVM程序,pid為程序號。
java -jar arthas-boot.jar pid
然後執行命令
trace xxx.util.bigDataUtil.BigDataHttpConsumer consume
這條命令的左右就是,追蹤xxx.util.bigDataUtil.BigDataHttpConsumer類裡consume方法的執行過程。
執行的結果如下,每一行最後的是程式碼行數,我們可以看一下,跟上面程式碼是一一對應的。
從程式碼中可以看到,如果返回碼是200,那麼它會執行第52行,如果返回碼不是200,會執行55行,因此,我們通過trace功能確定執行了哪條語句,就可以知道到底返回沒返回200,從結果來看,確定返回的不是200。
這樣我們就有了確定的證據證明發給後臺時返回非200,後臺同事檢查了自己的配置發現配置有誤,是他們自己的問題