Getting Spring Application Context to restore the problem scene using Arthas

Keywords: Programming Spring Java curl shell

background

Recently, a young monk intern has arranged for him to implement the small function of testing the connectivity of the target website. Simply speaking, the shell script below will be replaced by Java code to achieve it.

#!/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": "Baidu platform status is not normal, please note!"
        },
        "isAtAll": true
      }'

fi

Functional realization

Using spring task

@Scheduled(cron = "0 0 0/1 * * ? ")
public void startSchedule() {
    log.info("Start executing timed tasks to test Baidu's website connectivity");
    try {
        HttpResponse response = HttpRequest.get("").execute();
        if (HttpStatus.HTTP_OK != response.getStatus()) {
            this.send2DingTalk(response.getStatus());
        }
        log.info("Request Baidu to succeed, return message:{}",response.body());
    } catch (HttpException e) {
        log.error("Request Abnormal Baidu:{}", e);
        this.send2DingTalk(e.getMessage());
    }
    log.info("Complete the task of testing Baidu's website connectivity");
}

Problem Description

Deployed on the server, my old jio had already called the task status abnormal, but my younger brother's Java code still did not execute the notification.

  • To turn over the production log, only input the beginning and not output the end of the timed task, feel where the stuck, assume that if the timeout will always go to the catch logic, the search is fruitless.
  • Since the task is once an hour, how to quickly trigger the exception and restore the accident scene
  • Because there is no graphical interface and API interface with simple Spring Task

Arthas restores the accident scene and re-triggers the task

The core takes spring context and executes its startSchedule method

Identifying monitoring points

  • Spring MVC requests are processed through the Request Mapping Handler Adapter to invokeHandler Method to the target interface.
  • In the RequestMappingHandlerAdapter class, there is 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;
    }
}
  • Arbitrarily execute a request to get the RequestMapping Handler Adapter target, and then execute getApplication Context

The tt command gets the Application Context

  • arthas performs tt
tt -t org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter invokeHandlerMethod
  • If a web request is executed arbitrarily, tt can be captured

  • According to the index of the target, execute the custom OGNL expression.

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

Use Application Context to get the timed task bean to execute startSchedule

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

ok task triggered again

Investigation of the cause of the accident is clear, because the tool class using hutool does not set timeout, resulting in unlimited waiting, so the catch logic is not executed.

summary

Posted by MarcAndreTalbot on Wed, 31 Jul 2019 19:06:59 -0700