前言
阿尔萨斯是一个类似于Btrace的JVM在线调试分析工具,具体可参考我之前写的一篇博客:利用JVM在线调试工具排查线上问题。本文分享笔者刚遇到的一个问题,虽然不复杂,但是很典型。
问题与分析过程
昨天上线遇到一个问题,交易后给大数据平台异步送数,但是他们说没收到数据,因为我们没有打日志,所以没有直接的证据证明是他们的问题而不是我们的问题。
送数的原理大致如下,就是交易主线程把数据放到队列里,然后异步线程从队列里把数据取出来,发送到后台。
<代码类="语言java ">队列: BlockingQueue队列=new BlockingQueue (); 同步线程: 空白sendMsg(消息味精){ queue.offer(味精); } 异步线程: 空白消耗(){ 消息味精=queue.take (); 而(味精!=null) { HttpClient.post(味精); 味精=queue.take (); } }代码>
具体送数的代码如下(加了行数):
<代码类="语言java "> 38公共无效消耗(地图味精){ 39 HttpClient HttpClient=new HttpClient(厘米); 40 PostMethod方法=new PostMethod (uri); 41岁的方法。addRequestHeader (“context-type”、“应用程序/x-www-form-urlencoded”); 42 JSONObject json=new JSONObject(味精); 43 NameValuePair [] params=new NameValuePair [2]; 44 params [0]=new NameValuePair(“主题”,主题); 45 params [1]=new NameValuePair(“价值”,json.toJSONString ()); 46//System.out.println (msg.toString ()); 47 logger.info (“BigDataHttp发送Json:“+ json.toJSONString ()); 48 method.addParameters (params); 49尝试{ 50 51 httpClient.executeMethod(方法); 52如果(method.getStatusCode ()==200) { 53 logger.info (“BigDataHttp反应(成功):”+ method.getResponseBodyAsString ()); 其他54}{ 55 logger.info (“BigDataHttp反应(错误):”+ method.getResponseBodyAsString ()); 56} 57}捕捉(异常e) { 58 logger.error (e.getMessage (), e); 59}最后{ 60 method.releaseConnection (); 61} 62}代码>
在日志里没有发现试里的异常,而比较遗憾的是,我们的日志虽然开了信息级别,但是因为日志量太大,所以只开了交易上送和下发报文的日志,其他的日志都关了。
现在日志级别没法调,有没有办法能确定,请求返回了200年,还是其他值呢?
可以用在线调试工具阿尔萨斯,我们使用阿尔萨斯的痕迹功能,查看这个类执行的详细步骤。
首先连接上这个JVM进程,pid为进程号。
<代码> java jar arthas-boot。jar pid 代码>
然后执行命令
<代码> xxx.util.bigDataUtil痕迹。BigDataHttpConsumer消耗代码>
这条命令的左右就是,追踪xxx.util.bigDataUtil.BigDataHttpConsumer类里消费方法的执行过程。
执行的结果如下,每一行最后的是代码行数,我们可以看一下,跟上面代码是一一对应的。
从代码中可以看的到,如果返回码是200,那么它会执行第52行,如果返回码不是200人,会执行55行,因此,我们通过痕迹功能确定执行了哪条语句,就可以知道到底返回没返回200年,从结果来看,确定返回的不是200 .
这样我们就有了确定的证据证明发给后台时返回非200年后台同事检查了自己的配置发现配置有误,是他们自己的问题。