背景
最近來了個(gè)實(shí)習(xí)僧小弟疼蛾,安排他實(shí)現(xiàn)對(duì)目標(biāo)網(wǎng)站 連通性檢測(cè)的小功能,簡(jiǎn)單講就是將下邊的shell 腳本換成Java 代碼來實(shí)現(xiàn)
#!/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": "百度平臺(tái)狀態(tài)不正常瓣铣,請(qǐng)注意!"
},
"isAtAll": true
}'
fi
功能實(shí)現(xiàn)
使用spring task
@Scheduled(cron = "0 0 0/1 * * ? ")
public void startSchedule() {
log.info("開始執(zhí)行定時(shí)任務(wù) ,檢測(cè)百度網(wǎng)站連通性");
try {
HttpResponse response = HttpRequest.get("").execute();
if (HttpStatus.HTTP_OK != response.getStatus()) {
this.send2DingTalk(response.getStatus());
}
log.info("請(qǐng)求百度成功沦偎,返回報(bào)文:{}",response.body());
} catch (HttpException e) {
log.error("請(qǐng)求異常百度:{}", e);
this.send2DingTalk(e.getMessage());
}
log.info("執(zhí)行檢測(cè)百度網(wǎng)站連通任務(wù)完畢");
}
問題描述
部署在服務(wù)器上木张,我的老jio本 都已經(jīng)呼叫任務(wù)狀態(tài)不正常了,可是小弟的Java 代碼還是沒有執(zhí)行通知
- 去翻生產(chǎn)日志,只輸入了開始并沒有輸出定時(shí)任務(wù)結(jié)束煤蚌,感覺是哪里卡死耕挨,想當(dāng)然以為如果超時(shí)總會(huì)到catch 邏輯细卧,排查無果
- 由于任務(wù)是一小時(shí)一次,如何快速觸發(fā)一下這個(gè)異常筒占,還原事故現(xiàn)場(chǎng)
- 由于使用簡(jiǎn)單的Spring Task 沒有圖形化界面和API接口
Arthas 還原事故現(xiàn)場(chǎng)贪庙,重新觸發(fā)任務(wù)
核心拿到 spring context 然后執(zhí)行它的 startSchedule
方法
確定監(jiān)控點(diǎn)
- SpringMVC 的請(qǐng)求會(huì)通過
RequestMappingHandlerAdapter
執(zhí)行invokeHandlerMethod
到達(dá)目標(biāo)接口上進(jìn)行處理 - 而在
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;
}
}
- 任意執(zhí)行一次請(qǐng)求獲取到
RequestMappingHandlerAdapter
target 目標(biāo),然后執(zhí)行getApplicationContext
tt命令 獲取到ApplicationContext
- arthas 執(zhí)行 tt
tt -t org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter invokeHandlerMethod
-
任意執(zhí)行一次web 請(qǐng)求翰苫,tt 即可捕獲
根據(jù)目標(biāo)的索引止邮,執(zhí)行自定義 OGNL 表達(dá)式即可
tt -i 1019 -w 'target.getApplicationContext()'
使用ApplicationContext獲取 定時(shí)任務(wù)bean 執(zhí)行 startSchedule
tt -i 1000 -w 'target.getApplicationContext().getBean("baiduSchedule").startSchedule()'
ok 任務(wù)重新觸發(fā)了
事故原因調(diào)查清楚,由于使用hutool 的工具類 沒有設(shè)置timeout 導(dǎo)致無限等待奏窑,所以沒有執(zhí)行catch 邏輯
總結(jié)
- 以上嚇哭實(shí)習(xí)僧的操作
禁止
生產(chǎn)操作导披,只是提供個(gè)思路 ,當(dāng)然可以衍生其他業(yè)務(wù)場(chǎng)景的操作 - 核心是通過Arthas 來抓取Spring ApplicationContext 對(duì)象埃唯,然后獲取bean 進(jìn)行執(zhí)行方法
- 關(guān)于Arthas 是Alibaba開源的Java診斷工具撩匕,深受開發(fā)者喜愛
-
歡迎關(guān)注我們獲得更多的好玩JavaEE 實(shí)踐 :