Java面试题~面试官:你是怎么定位、排查、诊断生产环境的Bug的?

作者: 修罗debug
版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。


作为一名Java程序猿,“沟通需求”、“设计数据库”、“建表”以及“编码开发”是家常便饭的事,每天几乎都得重复性干这样的活,有的甚至还乐此不彼!(当然啦,前提是钱给到位了~~);但若要问起他们对什么东西相当敏感、甚至偶尔还会出现反感的话,那当属Bug和一些疑难杂症 无疑了!而如何在线上生产环境快速定位、排查以及诊断相应的Bug、解决相应的疑难杂症便成为了一个值得探讨的话题,话不多说,咱们直接进入正文!!!

    先不绕弯子,咱们直接先说答案吧:借助Alibaba开源的Java诊断工具Arthas可以快速直观地定位、排查、诊断生产环境中的Bug

      这时候就有小伙伴可能会问了,这家伙是啥玩意?怎么就可以快速定位、排查、诊断生产环境的Bug?它在实际生产环境中又是怎么用的呢?能不能来点实际的啊?……   


    别急啊,容debug娓娓道来………先说说Arthas是啥玩意吧:

    这家伙是“Alibaba开源的Java应用线上诊断工具,深受开发者喜爱”,这是Arthas的官方定义,enenen……这丫的也太短了吧………,算了,大道至简,这丝毫不影响debug对它的爱慕,感兴趣的小伙伴可以点击其开源地址:

(1)https://github.com/alibaba/arthas/blob/master/README_CN.md  

(2)https://gitee.com/arthas/arthas

附注:有些小伙伴可能访问不了github,没关系,点击第(2)个链接,那是debug专门为大伙儿找的对应的码云的地址;   


接下来,我们来看一下Arthas可以解决什么样的问题?直接看官网的介绍吧:


    毋庸置疑,这是一款强大而且好用的线上诊断工具,若用得好,相信可以干掉许多线上生产环境的疑难杂症,特别是在前后端分离开发、部署的模式下,诸如 快速定位前端传递的参数、查看接口返回的结果、查看接口执行的方法路径及其对应的耗时、监控整个Java应用的内存/CPU等指标的占用等情况,在Arthas面前可以说是小菜一碟


    那么在实际生产环境中该如何使用呢?还是来点实际的吧:

1)这里我们以Linux环境中部署的“程序员实战基地 fightjava.com” 的课程中心 板块的接口为案例,一同学习并实战Arthas在实际生产环境中的使用;其中这个接口的方法所在的全限定类名为:

com.debug.coding.fight.server.controller.web.IndexCourseController.center()

对应的完整的代码如下所示:

@RestController
public class IndexCourseController extends IndexWebAbstractController{

private static final Logger log= LoggerFactory.getLogger(IndexCourseController.class);

//首页课程中心
@RequestMapping(value = prefix + "/center", method = RequestMethod.GET)
public BaseResponse center(@Validated IndexCourseQuery query, BindingResult result){
if (result.hasErrors() || query.getPageNo() <= 0 || query.getPageSize() <= 0) {
return new BaseResponse(StatusCode.InvalidParams);
}
BaseResponse response = new BaseResponse(StatusCode.Success);
try {
//其中indexCourseService.indexCourseCenter(query)为具体执行的代码逻辑
response.setData(indexCourseService.indexCourseCenter(query));
} catch (Exception e) {
return new BaseResponse(StatusCode.Fail.getCode(), e.getMessage());
}
return response;
}
}

    其中,该方法的请求参数为IndexCourseQuery,其定义如下所示:

@Data
@ToString
public class IndexCourseQuery implements Serializable {
@NotNull
private Integer pageNo=1;
@NotNull
private Integer pageSize=Constant.COURSE_CENTER_PAGE_SIZE;

private String search;
private Integer typeId;
}

    而响应结果是塞到BaseResponse类中的,其结果是indexCourseService服务类调用indexCourseCenter()方法返回的,类型为:Map<String, Object>,里面有许多核心数据,在这里就不贴出来了,大伙儿可以访问https://www.fightjava.com/ 然后,点击课程中心,F12即可看到请求接口链接后返回的响应结果:


2OK,介绍了那么多,可能有些小伙伴有疑惑“这跟Arthas有啥关系?” 实不相瞒,还真有关系,因为debug将以这个板块、接口为案例,基于Linux环境查看整个Java应用的资源分配情况、接口调用的入参、接口返回的结果、接口方法调用的路径及其对应的耗时………那就直接来吧!   


3)首先,先执行以下命令,将Arthas诊断工具下载到Linux环境某个目录(也可以前往这个链接手动进行下载然后上传到服务器的某个文件目录下:http://fightjava.com/web/index/resource/17),然后将其启动,命令如下所示:

curl -O https://arthas.aliyun.com/arthas-boot.jar

java -jar arthas-boot.jar

    稍等片刻,即可成功启动,如下图所示:


4)试试dashboard命令吧,可以查看“程序员实战基地官网”这一Java应用的线程、内存、GC以及运行时相关信息(JDK版本等等),如下图所示:


5)接下来是比较常用的trace 命令:查看接口方法中的调用路径以及相关耗时情况;先按下ctrl+c,终止上次命令的结果查看,然后键入命令:

trace  com.debug.coding.fight.server.controller.web.IndexCourseController center

回车进入等待状态,如下图所示:


    然后在postman发起上述接口的调用,在这里,因为该接口对应的是程序员实战基地官网的“课程中心”首页:https://www.fightjava.com/web/index/course.html ,因此debug就直接打开浏览器访问了,之后,回到上图的命令行界面,可以看到结果了,如下图所示:


    可以看到,该请求方法内部有分叉开了几条调用路径,其中红色的表示耗时最长的,即IIndexCourseService服务类下的indexCourseCenter()请求方法,如下所示:

com.debug.coding.fight.server.service.web.IIndexCourseService:indexCourseCenter()

    在这里因为耗时才8.x毫秒,因此也不算太长,在这里就没必要跟踪下去了;倘若该该调用链耗时达到几秒或者十几秒,那就需要再次使用该命令再次对其进行跟踪:

trace  debug.coding.fight.server.service.web.IIndexCourseServic  indexCourseCenter

    利用此命令,可以知晓一个请求方法中到底是哪个子调用链响应慢或者出问题了!

6)紧接着是debug经常用到的核心命令:watch 了,其详细的文档可以看这里:https://arthas.aliyun.com/doc/watch ,下面debug带诸位一起感受一下它的常见用法!

    A.首先是查看该请求中前端传递到后端接口的参数列表,命令如下所示:

watch com.debug.coding.fight.server.controller.web.IndexCourseController center {params} -x 2

    其中,{}中的params代表该命令将查看该接口方法的入参,-x 2表示显示出两个层级的内容;需要说明的是 params为数组类型,表示参数数组,上述IndexCourseController类中的center方法拥有两个参数,因此它的size=2,该控制器类的方法定义如下图所示:


    返回结果如下所示:


    从该结果中就可以很直截了当的知晓前端传递过来了什么参数,如果将 –x 2 调整为 –x 3,那么将可以看到BindingResult 中的详细参数了!

    B.如果还想看到该接口的请求方法最终返回的结果,则可以通过如下的命令查看:

watch com.debug.coding.fight.server.controller.web.IndexCourseController center {params,returnObj} -x 2

    其返回结果如下所示:


      C.上图该结果,我只是看到了response中的hashMap,那里面是啥东西呢,别急,可以执行这一命令查看更多层级的内容:   

watch com.debug.coding.fight.server.controller.web.IndexCourseController center {returnObj} -x 5

    其返回结果如下所示:


7)除此之外,还有 tt –t 命令、Monitor命令、ThreadjadmcClassLoader等命令,这几个debug用得倒不是很多,因此就不介绍了,感兴趣的小伙伴可以自行前往其开源的官网照着撸一下!

 至此,debug算是将Java应用线上诊断工具Arthas介绍完了,双11快到了,建议可以上阿里云采购一台ECS(新用户听说0.95折),然后自建一个项目,写几个接口最后部署上ECS服务器,最后再按照本文debug介绍的一步步实战Arthas吧!!!


总结

本文我们一起撸下了一个Java应用常用的线上诊断工具Arthas,毫不客气地讲,这家伙偶尔还是可以起到神助攻的作用,因此强烈建议各位小伙伴拿下它!好了,本文就介绍到这里了吧,我是debug,一个相信技术改变生活、技术成就梦想 的直男屌丝!!!

如果本文对你有帮助,请关注公众号,并动动手指收藏、点赞、以及转发哦!!!   

备注:上述下载链接如果失效,可以加debug微信:debug0868  告知并领取(想学习更多的技术干货可以关注debug的技术公众号,不迷路)!!!