利用阿尔萨斯定位线上问题实例

  

前言

  

阿尔萨斯是一个类似于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年后台同事检查了自己的配置发现配置有误,是他们自己的问题。

利用阿尔萨斯定位线上问题实例