使用Arthas 獲取Spring ApplicationContext還原問題現場

背景

最近來了個實習僧小弟,安排他實現對目標網站 連通性檢測的小功能,簡單講就是將下邊的shell 腳本換成Java 代碼來實現web

#!/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 代碼仍是沒有執行通知spring

  • 去翻生產日誌,只輸入了開始並無輸出定時任務結束,感受是哪裏卡死,想固然覺得若是超時總會到catch 邏輯,排查無果
  • 因爲任務是一小時一次,如何快速觸發一下這個異常,還原事故現場
  • 因爲使用簡單的Spring Task 沒有圖形化界面和API接口

Arthas 還原事故現場,從新觸發任務

核心拿到 spring context 而後執行它的 startSchedule 方法shell

肯定監控點

  • 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 便可捕獲
    json

  • 根據目標的索引,執行自定義 OGNL 表達式便可api

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

使用ApplicationContext獲取 定時任務bean 執行 startSchedule

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

ok 任務從新觸發了bash

事故緣由調查清楚,因爲使用hutool 的工具類 沒有設置timeout 致使無限等待,因此沒有執行catch 邏輯服務器

總結

相關文章
相關標籤/搜索