tomcat卡死,如何1分钟排查出问题所在

背景

因为tomcat的http线程池,默认是200, 如果线程池耗尽,则会出现无法提供服务的情况。

故障模拟

某些情况下,可能http的TPS不高,但是内部程序有bug,导致了tomcat的http线程池的卡死。本文将会总结1分钟内排查出问题的方法。以下为示例:

 假设有一个Controller方法,模拟调用某个业务:

@RestController
@RequestMapping("/biz")
public class BizController {
 
    @GetMapping("/fire")
    public String fire(){
        return RpcInvoker.getUserInfo();
    }
}


模拟业务的代码,这段逻辑中,readline里面是有锁的保护,不允许并发读取:

public class RpcInvoker {
 
    public static String getUserInfo(){
        Scanner scanner = new Scanner(System.in);
        scanner.nextLine();
        return "done";
    }
}


此时,使用ApiPost进行批量调用,或者 PostMan也行,我比较喜欢用ApiPost,使用【一键压测】功能,并发数超过200,举例:改到300。

 

点击压测后,马上就会发现,不能正常执行完请求。浏览器访问 /biz/fire 也无响应,此时模拟了tomcat的卡死。那么故障已经发生,现在需要马上定位问题。

线程dump

执行 jps -l 列出全部的java进程

找到目标的SpringBootTomcatMain的java进程,pid是 34280,

执行 jstack -l 34280 > stack.log  导出当前堆栈信息,但是堆栈信息内容很多,一般大小超出1M,很难直接肉眼查看

jstack堆栈分析


打开 http://ctbots.com

打开jstack的堆栈分析 日志上传页面:

上传堆栈文件,点击【开始分析】,分析出基本信息。

环境信息

展示了基本的dump的基本要素,包括:导出时间和JVM的版本。

线程状态及阻塞原因


我们主要关注是否存在BLOCK状态的线程(图中,我们发现了大量的BLOCK线程)。

点击按钮,查看线程详情:

确定被卡主的源头,点击【被别人卡住】 马上看到被block的原因:

 

调用分析


当tomcat卡死时,如何判断高频调用,线程都执行在什么地方,可以点击【调用分析】,这里马上注意到我们的模拟的业务代码,大量在的出现在线程中:

点击查看,发现全部被BLOCK掉,所以 调用会出现这么多次。

至此,我们就能快速地在1分钟内 分析完tomcat卡死的原因了。

posted @ 2023-06-14 19:04  learn_cat  阅读(1459)  评论(0)    收藏  举报