java线上服务假死

线上服务最近老是莫名其妙假死,但是没有挂掉。

服务器升级到8核32g还是会出现。

重启就好了,用jprofiler排查内存也没满,cpu也没满…

可以私信我,如果解决额外有茶水费。

有什么排查方案吗,尽可能详细到命令。

jstack工具就很好用功能也很强大,网上简单查一下使用方法就知道咋用了
用arthas工具排查链路耗时,art has功能也是非常强大的

至于问题不到现场也不知道具体是什么原因,你可以按这个思路去排查

1检查一下当时访问量大不大,检查一下线程是不是被打满了导致在并发大的时候,服务出现假死
2 检查服务的网络延迟,看看是不是网络原因
3 检查一下是不是部分sql导致的问题,导致数据库被占满,或者数据库数据量太大 某些查询太耗时,代码的模糊查询、索引是否合理是否分裤分表等
4 还有tomcat服务器分配的资源怎么样,是不是太少了 看看日志
5 代码是不是有问题 出现死循环 看看每部分的耗时
6 如果是分布式项目 看看负载均衡是不是做的有问题
上面就是我的一些经验总结 可以参考一下

个人感觉是代码的问题,有些代码写的不规范,占用了大量内存,造成系统卡死。可以使用java内存监控工具测试一下
另外就是确认一下数据库磁盘空间是否满了,这个也是经常遇到的原因之一

1️⃣假死现象
服务程序假死具有以下特征:

  1. 程序对请求没有任何响应;
  2. 程序请求时没有任何日志输出;
  3. 程序进程存在,通过jps或者ps查看进程,可以看到服务进程存在;

2️⃣ 造成假死的可能原因

  1. java线程出现死锁,或所有线程被阻塞;
  2. 数据库连接池中的连接耗尽,导致获取数据库连接时永久等待;
  3. 出现了内存泄漏导致了OutOfMemory,内存空间不足导致分配内存空间持续失败;服务器的可用内存足够,但是分配给jvm的内存被耗尽的情况,容易出现这种情况;
  4. 服务程序运行过程中替换了jar包,但是没有进行重启服务,这属于不按规则操作引起的问题;
  5. 磁盘空间满,导致需要写数据的地方全部失败;
  6. 线程池满,无法分配更多的线程来处理请求,通常是因为线程被大量阻塞在某个请求上;

3️⃣分析方法

  1. 通过jstat查看内存使用和垃圾回收情况,查看内存占用情况以及垃圾回收情况是否异常;
  2. 通过jmap -heap查看内存分配情况,查看是否内存空间被占满,导致无法分配足够的内存空间;
  3. 通过jstack -F pid查找线程死锁,导出线程堆栈,然后查看线程状态;
  4. 通过gclog查看垃圾回收原因,需要在服务启动时指定记录垃圾回收日志;
  5. 通过jmap -dump:format=b,file=heap.bin 导出内存镜像文件,使用工具进行分析;
  6. 通过jmap -histo查看内存对象;
    具体可以看一下这位博主总结的内容:
    java服务程序假死(进程存在但请求无响应)的几种原因_程序猿(攻城狮)的博客-CSDN博客_服务假死 java服务程序假死(进程存在但请求无响应)的几种原因 https://blog.csdn.net/liaomingwu/article/details/125160302

可能 java线程出现死锁 可以查看日志寻找问题的所在

自己开发的话,检查下是不是有什么数据库链接没关闭之类的,或者是流之类的没关闭的,要是es这些产品,可能是他们本身要求的线程数有点高,可以试着调整参数

感觉是代码的问题

根据描述,最类似该情况的例子,java调用shell脚本,如Oracle 的sqlldr脚本加载数据到数据库。
脚本执行时产生日志和错误信息,java的缓冲器填满,java线程即hang。
解决办法可以在java程序中处理缓冲区,也可以简单的把shell脚本的输出定向到文件解决。

我私信你,之前遇到过,整理一下经验发你

是否有多线程或者死循环将资源耗尽了,排查下

看看线程的个数,看看每个线程都卡在哪?有没相似的地方

我一般用 visualvm 或 jstat(两者都是 JDK 的一部分)。 您可以查看线程的当前状态并检查是否有任何应用程序错误..

其他有助于查看内部进程的 linux 工具:

lsof : 可以检查进程是否打开了太多文件
strace:从系统调用的角度查看当前活动。

https://blog.csdn.net/TheLongir/article/details/124629717

这个应该是你的代码出现问题了
不知道你的程序是否有记录日志的,如果有,根据日志去排查,这样是最快定位到问题所在的