您现在的位置是:首页 > 文章详情

使用Arthas 获取Spring ApplicationContext还原问题现场

日期:2019-08-01点击:266

背景

最近来了个实习僧小弟,安排他实现对目标网站 连通性检测的小功能,简单讲就是将下边的shell 脚本换成Java 代码来实现

#!/bin/bash URL="https://www.baidu" HTTP_CODE=`curl -o /dev/null -s -w "%{http_code}" "${URL}"` #echo $HTTP_CODE if [ $HTTP_CODE != '200' ];then curl 'https://oapi.dingtalk.com/robot/send?access_token=xx' \ -H 'Content-Type: application/json' \ -d '{"msgtype": "text", "text": { "content": "百度平台状态不正常,请注意!" }, "isAtAll": true }' fi 

功能实现

使用spring task

@Scheduled(cron = "0 0 0/1 * * ? ") public void startSchedule() { log.info("开始执行定时任务 ,检测百度网站连通性"); try { HttpResponse response = HttpRequest.get("").execute(); if (HttpStatus.HTTP_OK != response.getStatus()) { this.send2DingTalk(response.getStatus()); } log.info("请求百度成功,返回报文:{}",response.body()); } catch (HttpException e) { log.error("请求异常百度:{}", e); this.send2DingTalk(e.getMessage()); } log.info("执行检测百度网站连通任务完毕"); } 

问题描述

部署在服务器上,我的老jio本 都已经呼叫任务状态不正常了,可是小弟的Java 代码还是没有执行通知

  • 去翻生产日志,只输入了开始并没有输出定时任务结束,感觉是哪里卡死,想当然以为如果超时总会到catch 逻辑,排查无果
  • 由于任务是一小时一次,如何快速触发一下这个异常,还原事故现场
  • 由于使用简单的Spring Task 没有图形化界面和API接口

Arthas 还原事故现场,重新触发任务

核心拿到 spring context 然后执行它的 startSchedule 方法

确定监控点

  • SpringMVC 的请求会通过 RequestMappingHandlerAdapter 执行invokeHandlerMethod 到达目标接口上进行处理
  • 而在 RequestMappingHandlerAdapter类中有 getApplicationContext()
@Nullable public final ApplicationContext getApplicationContext() throws IllegalStateException { if (this.applicationContext == null && this.isContextRequired()) { throw new IllegalStateException("ApplicationObjectSupport instance [" + this + "] does not run in an ApplicationContext"); } else { return this.applicationContext; } } 
  • 任意执行一次请求获取到 RequestMappingHandlerAdapter target 目标,然后执行 getApplicationContext

tt命令 获取到ApplicationContext

  • arthas 执行 tt
tt -t org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter invokeHandlerMethod 
  • 任意执行一次web 请求,tt 即可捕获

  • 根据目标的索引,执行自定义 OGNL 表达式即可

tt -i 1019 -w 'target.getApplicationContext()' 

使用ApplicationContext获取 定时任务bean 执行 startSchedule

tt -i 1000 -w 'target.getApplicationContext().getBean("baiduSchedule").startSchedule()' 

ok 任务重新触发了

事故原因调查清楚,由于使用hutool 的工具类 没有设置timeout 导致无限等待,所以没有执行catch 逻辑

总结

原文链接:https://my.oschina.net/giegie/blog/3081896
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章