作为一名Java程序猿,“沟通需求”、“设计数据库”、“建表”以及“编码开发”是家常便饭的事,每天几乎都得重复性干这样的活,有的甚至还乐此不彼!(当然啦,前提是钱给到位了~~);

但若要问起他们对什么东西相当敏感、甚至偶尔还会出现反感的话,那当属Bug和一些疑难杂症 无疑了!而如何在线上生产环境快速定位、排查以及诊断相应的Bug、解决相应的疑难杂症便成为了一个值得探讨的话题,话不多说,咱们直接进入正文!!!

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

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




调用jar包执行mysql 语句 调用jar包接口_生产环境


别急啊,容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专门为大伙儿找的对应的码云的地址;


调用jar包执行mysql 语句 调用jar包接口_java_02


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


调用jar包执行mysql 语句 调用jar包接口_生产环境_03


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


调用jar包执行mysql 语句 调用jar包接口_调用jar包执行mysql 语句_04


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

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

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

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

@RestControllerpublic 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@ToStringpublic class IndexCourseQuery implements Serializable {    @NotNull    private Integer pageNo=1;    @NotNullprivate Integer pageSize=Constant.COURSE_CENTER_PAGE_SIZE;    private String search;    private Integer typeId;}

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


调用jar包执行mysql 语句 调用jar包接口_调用jar包执行mysql 语句_05


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


调用jar包执行mysql 语句 调用jar包接口_java_06


(3)首先,先执行以下命令,将Arthas诊断工具下载到Linux环境某个目录,然后将其启动,命令如下所示:

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

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


调用jar包执行mysql 语句 调用jar包接口_调用jar包执行mysql 语句_07


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


调用jar包执行mysql 语句 调用jar包接口_调用jar包执行mysql 语句_08


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

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

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


调用jar包执行mysql 语句 调用jar包接口_调用jar包执行mysql 语句_09


然后在postman发起上述接口的调用,在这里,因为该接口对应的是程序员实战基地官网的“课程中心”首页:

http://www.fightjava.com/web/index/course.html

因此debug就直接打开浏览器访问了,之后,回到上图的命令行界面,可以看到结果了,如下图所示:


调用jar包执行mysql 语句 调用jar包接口_调用jar包执行mysql 语句_10


可以看到,该请求方法内部有分叉开了几条调用路径,其中红色的表示耗时最长的,即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,该控制器类的方法定义如下图所示:


调用jar包执行mysql 语句 调用jar包接口_Java_11


返回结果如下所示:


调用jar包执行mysql 语句 调用jar包接口_Java_12


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

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

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

其返回结果如下所示:


调用jar包执行mysql 语句 调用jar包接口_把接口调用打成jar包的类怎么写_13


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

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

其返回结果如下所示:


调用jar包执行mysql 语句 调用jar包接口_把接口调用打成jar包的类怎么写_14


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

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


调用jar包执行mysql 语句 调用jar包接口_把接口调用打成jar包的类怎么写_15


总结:

本文我们一起撸下了一个Java应用常用的线上诊断工具Arthas,毫不客气地讲,这家伙偶尔还是可以起到神助攻的作用,因此强烈建议各位小伙伴拿下它!好了,本文就介绍到这里了吧!


后记

下面是Debug最近写的一些干货,每篇都很用心,欢迎各位小伙伴阅读/点赞/分享:

1.Java线程池实战总结一之百万数据的批量插入(java面试)

2.干货实战~Java如何防止接口重复提交

3.从一个线程并发安全场景谈谈Java的锁、CAS算法以及ABA问题

4.Java秒杀系统实战系列-数据库级别Sql的优化与代码的调整

5.Java秒杀系统实战系列-整合Shiro实现用户登录认证

我是debug,一个相信技术改变生活、技术成就梦想 的直男屌丝!!!如果本文对你有帮助,麻烦动动手指点赞或转发哦!!咱们下期见!