美文网首页
线上问题排查思路

线上问题排查思路

作者: 贪挽懒月 | 来源:发表于2023-09-19 10:59 被阅读0次

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

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

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

     total        used        free      shared  buff/cache   available
     Mem:       16256764     7583240     2177924     2901216     6495600     5437168
     Swap:       2097148        1280     2095868
    

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

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

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

    文件系统                  容量    已用  可用  已用%  挂载点
    xxxxxxxx                 7.8G     0   7.8G    5%   /xx
    ……
    

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

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

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

     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>,会显示线程的状态。

    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)
    

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

    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>命令,可以看到堆内存的使用情况。

    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的对象信息。

    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,一个个地看详情详情,一般看前几个就可以定位到问题了。

    相关文章

      网友评论

          本文标题:线上问题排查思路

          本文链接:https://www.haomeiwen.com/subject/fxkyjdtx.html