前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >线上问题排查思路

线上问题排查思路

作者头像
贪挽懒月
发布2023-10-16 15:33:41
1900
发布2023-10-16 15:33:41
举报
文章被收录于专栏:JavaEEJavaEE

若用户反馈线上服务请求无响应,可以按照以下步骤进行排查。

一、确认服务器内存使用情况

执行free命令,看看服务器内存是否正常。

代码语言:javascript
复制
 total        used        free      shared  buff/cache   available
 Mem:       16256764     7583240     2177924     2901216     6495600     5437168
 Swap:       2097148        1280     2095868

看起来服务器内存是正常的。

二、确认服务器磁盘使用情况

执行df -h命令,查看磁盘使用情况。

代码语言:javascript
复制
文件系统                  容量    已用  可用  已用%  挂载点
xxxxxxxx                 7.8G     0   7.8G    5%   /xx
……

磁盘空间看起来也是充足的。

三、查看哪个进程占用内存多

输入top命令,然后按 shift p,最前面的就是占用内存最多的。

代码语言:javascript
复制
 PID     USER     PR  NI    VIRT     RES    SHR S     %CPU %MEM   TIME+      COMMAND
32297   xxxxxx    20   0    109.7g   4.7g   4.0g S   46.2 30.2    160554:47    java

这里可以获取到占用内存最多的pid。

四、查看线程的堆栈信息

执行jstack <pid>,会显示线程的状态。

代码语言:javascript
复制
Full thread dump OpenJDK 64-Bit Server VM (17+35-2724 mixed mode, sharing):

Threads class SMR info:
_java_thread_list=0x00007f24080015b0, length=41, elements={
0x00007f266c0899e0, 0x00007f266c08b050, 0x00007f266c091d60, 0x00007f266c093280,
0x00007f266c0948a0, 0x00007f266c0964a0, 0x00007f266c097c00, 0x00007f266c0a12a0,
0x00007f266c0befe0, 0x00007f266c0fa7d0, 0x00007f266c23c6b0, 0x00007f266c26dab0,
0x00007f266c425430, 0x00007f266c5ce320, 0x00007f266c6a3ca0, 0x00007f266c6e9790,
0x00007f266c9297f0, 0x00007f266c92d740, 0x00007f266c95d4a0, 0x00007f266c027640,
0x00007f23b8005600, 0x00007f23dc55f2c0, 0x00007f23dc5705c0, 0x00007f23bc0b8bc0,
0x00007f23bc15ebf0, 0x00007f23bc1e0cd0, 0x00007f23b800b850, 0x00007f23b800c2e0,
0x00007f23b800d370, 0x00007f23b800e9d0, 0x00007f23b800fbd0, 0x00007f23b8010ee0,
0x00007f23b8012220, 0x00007f23c4439b80, 0x00007f23c4006500, 0x00007f23c46ae980,
0x00007f23544eeb00, 0x00007f237c406d00, 0x00007f23a829ba30, 0x00007f23c46b2560,
0x00007f2408000a90
}

"Reference Handler" #2 daemon prio=10 os_prio=0 cpu=1463269.24ms elapsed=23238405.12s tid=0x00007f266c0899e0 nid=0x7e38 waiting on condition  [0x00007f26542be000]
   java.lang.Thread.State: RUNNABLE
        at java.lang.ref.Reference.waitForReferencePendingList(java.base@17/Native Method)
        at java.lang.ref.Reference.processPendingReferences(java.base@17/Reference.java:253)
        at java.lang.ref.Reference$ReferenceHandler.run(java.base@17/Reference.java:215)

如果有死锁,就会有下面这种:

代码语言:javascript
复制
java.lang.Thread.State: BLOCKED
     at xxxxxx1
     - waiting to lock <0xxxxxx>
     - locked <1xxxxx>
java.lang.Thread.State: BLOCKED
     at xxxxxx2
     - waiting to lock <1xxxxxx>
     - locked <0xxxxx>
五、查看堆内存占用情况

执行jmap -heap <pid>命令,可以看到堆内存的使用情况。

代码语言:javascript
复制
Attaching to process ID 5064, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.271-b09

using thread-local object allocation.
Parallel GC with 8 thread(s)

Heap Configuration:
   MinHeapFreeRatio         = 0
   MaxHeapFreeRatio         = 100
   MaxHeapSize              = 536870912 (512.0MB)
   NewSize                  = 268435456 (256.0MB)
   MaxNewSize               = 268435456 (256.0MB)
   OldSize                  = 268435456 (256.0MB)
   NewRatio                 = 2
   SurvivorRatio            = 8
   MetaspaceSize            = 134217728 (128.0MB)
   CompressedClassSpaceSize = 260046848 (248.0MB)
   MaxMetaspaceSize         = 268435456 (256.0MB)
   G1HeapRegionSize         = 0 (0.0MB)

Heap Usage:
PS Young Generation
Eden Space:
   capacity = 241172480 (230.0MB)
   used     = 94437072 (90.06221008300781MB)
   free     = 146735408 (139.9377899169922MB)
   39.15748264478601% used
From Space:
   capacity = 13107200 (12.5MB)
   used     = 3045992 (2.9048843383789062MB)
   free     = 10061208 (9.595115661621094MB)
   23.23907470703125% used
To Space:
   capacity = 12582912 (12.0MB)
   used     = 0 (0.0MB)
   free     = 12582912 (12.0MB)
   0.0% used
PS Old Generation
   capacity = 268435456 (256.0MB)
   used     = 84914376 (80.98065948486328MB)
   free     = 183521080 (175.01934051513672MB)
   31.63307011127472% used

46153 interned Strings occupying 5019920 bytes.

这里可以看到伊甸园区、from区、to区和老年代的内存占用情况,如果老年代99.99%了,那就是堆内存溢出了。

六、查看堆内存中内存占用前10的对象信息

jmap -histo:live <pid> | head -n 10 执行这个命令,可以看到内存占用前10的对象信息。

代码语言:javascript
复制
num     #instances         #bytes  class name
----------------------------------------------
   1:        165329       18150792  [C
   2:        163258        3918192  java.lang.String
   3:         40481        3562328  java.lang.reflect.Method
   4:         28014        2844936  [Ljava.lang.Object;
   5:         67703        2166496  java.util.concurrent.ConcurrentHashMap$Node
   6:          7919        2106384  [B
   7:         17131        1934896  java.lang.Class

如果这里看到有自己写的类对象,那可能就可以找到问题了。

七、分析内存溢出问题

确定了是哪一个节点有问题,那么先把节点的流量切走。 如果第六步没分析出来是什么导致内存溢出,可以按如下步骤排查。

1. 导出dump文件 jmap -dump:format=b,live,file=<fileName>.hprof <pid> 执行该命令,可以导出名为fileName.hprof的dump文件

2. 分析dump文件 这里介绍使用mat工具分析dump文件。

  • 先点击mat工具的 window ---> preferences ---> memory Analyzer,把 keep unreachable objects 勾选上,勾上了会保留不可达对象;
  • 点击 file ---> open heap dump,选择刚才的dump文件,等待几分钟,mat工具会生成一个默认的报告;
  • 默认报告里会列出problems,点击details就可以看到问题详情,一般会列出有问题的对象;
  • 选择有问题的对象,右键Merge Shortest Paths to GC Roots ---> exclude weak references
  • 然后再Java Basics ---> Thread Details,这样就可以看到线程详情,线程详情中就会有错误信息,可以定位到在代码的哪一行报错了;

如果默认报告按照上面的方式定位不到具体代码,那可以尝试以下步骤:

  • 在overview页点击histogram,然后按照retained heap排序;
  • 然后选择默认排在前面的对象,右键merge shortest path to GC Roots
  • 然后选择线程,Java Basics ---> Thread Details,一个个地看详情详情,一般看前几个就可以定位到问题了。
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2023-09-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、确认服务器内存使用情况
  • 二、确认服务器磁盘使用情况
  • 三、查看哪个进程占用内存多
  • 四、查看线程的堆栈信息
  • 五、查看堆内存占用情况
  • 六、查看堆内存中内存占用前10的对象信息
  • 七、分析内存溢出问题
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档