不喜歡看文字可以跳轉(zhuǎn)[B站視頻](https://www.bilibili.com/video/BV1vy4y1q7GQ/)
定時任務(wù)備份表task數(shù)據(jù)到task_history中娇昙,備份后將原數(shù)據(jù)刪除较坛。
如下示例:
```
? ? @Scheduled(fixedDelay = 5)
? ? public String taskBackUp() {
? ? ? ? while (true) {
? ? ? ? ? ? try {
? ? ? ? ? ? ? ? boolean flag = selfProxy.process();
? ? ? ? ? ? ? ? if (flag) break;
? ? ? ? ? ? } catch (Exception e) {
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? return "success";
? ? }
? ? @Transactional(rollbackFor = Exception.class)
? ? public boolean process() {
? ? ? ? List<Task> list = taskMapper.getList();
? ? ? ? if (CollectionUtils.isEmpty(list)) {
? ? ? ? ? ? return true;
? ? ? ? }
? ? ? ? List<TaskHistory> historyList = list.stream().map(t -> {
? ? ? ? ? ? TaskHistory ts = new TaskHistory();
? ? ? ? ? ? BeanUtils.copyProperties(t, ts);
? ? ? ? ? ? return ts;
? ? ? ? }).collect(Collectors.toList());
? ? ? ? //將數(shù)據(jù)插入歷史表
? ? ? ? taskHistoryMapper.insert(historyList);
? ? ? ? //刪除原表數(shù)據(jù) 這里會報錯
? ? ? ? taskMapper.delete(list);
? ? ? ? return false;
? ? }
```
上線觸發(fā)定時任務(wù)后收到gc報警僚祷,應(yīng)用吞吐量下降。因為實現(xiàn)時出現(xiàn)bug導(dǎo)致delete時拋出異常生均,數(shù)據(jù)產(chǎn)生回滾奢浑,但是外層做了catch,不會打斷循環(huán)怕吴。也就是原本是想一點點備份數(shù)據(jù)直到備份完成,但是因為產(chǎn)生異常導(dǎo)致每次都是處理第一批數(shù)據(jù)县踢,造成了死循環(huán)转绷。這個是產(chǎn)生問題的原因,通過異常日志是能夠定位到的殿雪。
但是這個case我想在日志不明確時可以通過什么手段能定位到該問題呢暇咆?所以將異常日志移除。看是否通過其他手段定位到在異常信息不明確時定位到問題爸业。
答案:
在不確定的情況下還是整體看下進程情況吧其骄。
執(zhí)行`java -jar /chaosblade-0.6.0/arthas-boot.jar`選擇進程,輸入`dashboard`可以看到整體的情況扯旷。如圖:
可以看到有個線程**長期**占用CPU99%拯爽,這個線程肯定有問題。另外觀察到`gc.parnew.count`與`gc.concurrentmarksweep.count`增長的速度也比較快钧忽。
下面異常的線程在做什么:
執(zhí)行多次`thread 41(41是線程id)`可以看到都是在執(zhí)行sql查詢操作毯炮。
再去查看線程棧中對應(yīng)代碼以及sql查詢?nèi)罩颈隳軌蚨ㄎ坏绞钱a(chǎn)生了死循環(huán)導(dǎo)致的。
另外還有一種方式就是針對內(nèi)存做profile耸黑,查看到分配內(nèi)存最多的線程桃煎,然后看其線程棧也能找到原因,這種方法交給大家自己探索下大刊,有問題可以在下方留言为迈。