ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

记一次线上Java进程假死问题分析

2021-03-19 13:30:20  阅读:484  来源: 互联网

标签:分析 Java 查看 队列 假死 线程 线上 ArrayBlockingQueue 日志


背景

上午11点左右,监控系统突然发出来一个告警,分布式数据库的某个代理节点(Java编写)连接失败率100%,每次都是超时,赶紧登上后台去查看

问题分析

一、查看系统指标

  1. top命令查看一些基础指标,cpu使用率不高,内存一直都是80%左右,io,网络都没问题
  2. top -Hp Java进程的pid,查看进程内的情况,1786个sleep状态的线程
  3. 赶紧jstack了一份线程信息,发现很多线程都阻塞在了ArrayBlockingQueue的put方法上
  4. 紧接着dump一份内存映像,27个G,心累,还得找台大内存的电脑去分析

二、jstack信息分析

分析之前得先搞清楚一个线程的生命周期
线程生命周期

因为很多线程处于sleep状态,所以优先排查waiting和timed waiting状态的线程,一统计发现有1500多个,随机挑了几个,基本都是阻塞在ArrayBlockingQueue的put方法上,有这些信息就够了,接下来根据jstack里的线程信息ServerExecutor-2-thread-1101,再去分析dump文件
在这里插入图片描述

三、dump文件分析

工具我用的是MAT,还是挺好用的(前提是得有个牛逼的电脑O^O),先上个图,本次分析主要使用的是标黄的地方
在这里插入图片描述

查看线程情况,然后跟据jstack里获取到的线程id过滤一下,再一步步展开线程,看啊可能此线程在做什么,以及卡在哪里,从标黄的地方可以看出,此线程在执行一个batchInsert任务,执行任务之前呢要先记录一条日志,记录日志的动作是异步的,只是写入到一个ArrayBlockingQueue里,但是就是这个写入动作卡住了,查看ArrayBlockingQueue的地353行代码,当队列满了的时候,线程就会进入阻塞等待状态(基础好一点的同学不用翻代码也能猜到了)

在这里插入图片描述
在这里插入图片描述

四、综合分析

上一步分析到日志的队列满了(队列大小为100000),导致写日志操作都阻塞了,为什么写日志的队列会满呢,查看监控该节点并没有很大的并发,并且调整了权重让新的请求不再分发到这个节点之后,队列还是满的,一直持续,不见下降,另外一种可能就是从日志队列里取数据的操作停了,查看从队列里读数据的线程,发现确实停掉了,再结合服务器日志,发现是OOM导致的线程停止

解决方案

既然问题清晰了,解决方案也很简单,给从日志队列里读入据写入磁盘的操作加个try catch,catch Throwable对象,这样可以捕捉到OOM,避免线程因为OOM停止,加try catch的时候范围尽量小

标签:分析,Java,查看,队列,假死,线程,线上,ArrayBlockingQueue,日志
来源: https://blog.csdn.net/JB324/article/details/115004051

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有