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

背景

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

 1#!/bin/bash
 2URL="https://www.baidu"
 3HTTP_CODE=`curl -o /dev/null -s -w "%{http_code}" "${URL}"`
 4#echo $HTTP_CODE
 5if [ $HTTP_CODE != '200' ];then
 6curl 'https://oapi.dingtalk.com/robot/send?access_token=xx' \
 7   -H 'Content-Type: application/json' \
 8   -d '{"msgtype": "text",
 9        "text": {
10             "content": "百度平台状态不正常,请注意!"
11        },
12        "isAtAll": true
13      }'
14
15fi复制代码

功能实现

使用spring task

 1@Scheduled(cron = "0 0 0/1 * * ? ")
 2public void startSchedule() {
 3    log.info("开始执行定时任务 ,检测百度网站连通性");
 4    try {
 5        HttpResponse response = HttpRequest.get("").execute();
 6        if (HttpStatus.HTTP_OK != response.getStatus()) {
 7            this.send2DingTalk(response.getStatus());
 8        }
 9        log.info("请求百度成功,返回报文:{}",response.body());
10    } catch (HttpException e) {
11        log.error("请求异常百度:{}", e);
12        this.send2DingTalk(e.getMessage());
13    }
14    log.info("执行检测百度网站连通任务完毕");
15}复制代码

问题描述

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

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

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

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

确定监控点

  • SpringMVC 的请求会通过 RequestMappingHandlerAdapter 执行invokeHandlerMethod 到达目标接口上进行处理
  • 而在 RequestMappingHandlerAdapter类中有 getApplicationContext()
1@Nullable
2public final ApplicationContext getApplicationContext() throws IllegalStateException {
3    if (this.applicationContext == null && this.isContextRequired()) {
4        throw new IllegalStateException("ApplicationObjectSupport instance [" + this + "] does not run in an ApplicationContext");
5    } else {
6        return this.applicationContext;
7    }
8}复制代码

  • 任意执行一次请求获取到 RequestMappingHandlerAdaptertarget 目标,然后执行 getApplicationContext
tt命令 获取到ApplicationContext

  • arthas 执行 tt
1tt -t org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter invokeHandlerMethod复制代码

  • 任意执行一次web 请求,tt 即可捕获

  • 根据目标的索引,执行自定义 OGNL 表达式即可
1tt -i 1019 -w 'target.getApplicationContext()'复制代码

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

1tt -i 1000 -w 'target.getApplicationContext().getBean("baiduSchedule").startSchedule()'复制代码

ok 任务重新触发了

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

总结

以上吓哭实习僧的操作禁止生产操作,只是提供个思路 ,当然可以衍生其他业务场景的操作

核心是通过Arthas 来抓取Spring ApplicationContext 对象,然后获取bean 进行执行方法

关于Arthas 是Alibaba开源的Java诊断工具,深受开发者喜爱

欢迎关注我们获得更多的好玩JavaEE 实践

推荐阅读:

《深入理解 Java 内存模型》读书笔记

面试-基础篇

Spring Boot 2.0 迁移指南

SpringBoot使用Docker快速部署项目

为什么选择 Spring 作为 Java 框架?

SpringBoot RocketMQ 整合使用和监控

Spring Boot 面试的十个问题

使用 Spring Framework 时常犯的十大错误

SpringBoot Kafka 整合使用

SpringBoot RabbitMQ 整合使用

上篇好文:

如何优雅关闭 Spring Boot 应用

转载于:https://juejin.im/post/5d498a1af265da03e921b262

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值