美文网首页
GC 永久代溢出导致服务宕机

GC 永久代溢出导致服务宕机

作者: 朱万宇 | 来源:发表于2018-03-22 20:52 被阅读0次

现象

今天, 生产上的springboot 应用cpu 达到200%, 即占用了2核, 线上应用奔溃, 应用无法访问。在立刻重启应用后,应用恢复正常, 奇怪的是, 在一段时间后, 服务又出现无法访问的情况。

问题分析

该问题可以大致上看成2类, 可能也可能没有直接关联

  1. 服务宕机
  2. 应用占用CPU很高

排查思路及手段

因为不同的问题排查思路及方式会不同, 针对本次服务宕机的排查问题追溯如下:
通过jps查看应用是否运行 > 通过Top查看系统运行状况 > 查看错误日志 >

排查细节:

1、 使用jps查看是哪个进程编号pid 对应哪个应用

jps: Java Virtual Machine Process Status Tool

[root@localhost ~]#  jps             
26610 Bootstrap
28877 jar
18039 TSDMain
26091 Kafka
19456 Jps

如果发现应用不在列表中, 则本次服务无法访问则是因为应用未启动造成, 则需要排查是什么原因造成服务未启动。
可能原因:

  1. linux oom killer 将应用杀死
  2. 人为杀死(可能性很小)
  3. 操作系统宕机等原因(如果操作系统在云服务上,可能性极小)

此时, 我发现应用还在列表中。

2. 查看错误日志

java 应用在线上会以文件的形式记录warn级别及以上的错误日志, 发现有大量以下内容的错误日志:

   "Cannot serialize; nested exception is 
   org.springframework.core.serializer.support.SerializationFailedException: Failed to 
   serialize object using DefaultSerializer; nested exception is java.lang.OutOfMemoryError: 
   PermGen space"

以上错误很明显了: 内存溢出, 永久代内存空间不足。

2.1查看应用永久代内存空间大小
 >   jstat -gcpermcapacity pid                      #perm对象的信息及其占用量
  PGCMN      PGCMX       PGC         PC      YGC   FGC    FGCT     GCT   
   21504.0    83968.0    83968.0    83968.0   361     2    0.906   39.789

# 同时我们可以通过jstat -gcutil来动态查看gc的状态
> jstat -gcutil pid 
大致情况如下:
  S0     S1     E      O      P     YGC     YGCT    FGC    FGCT     GCT   
  0.00  11.13  11.97  40.61  33.67   5508   44.783    22   10.686   55.469
(以上是jvm参数加入后的状态, 之前看到P是99%以上)

经过换算, 发现perm代的最大容量才81M。

本次解决办法:

设置jvm参数, 增大永久代内存的大小
(java -XX:MaxPermSize=512M -jar xxxx.jar &)
之后服务不再出现无法提供服务的问题。

事后回顾及思考:

应用通过jenkins发布, 构建后执行脚本运行springboot的应用, 采用的是java -jar xxx.jar , 故采用默认配置, 从而忽略了生产对于内存要求的苛刻性。
所以对于生产环境的配置, 往往要结合并分析实际业务场景, 选择适合的配置, 当然有时候不能盲目加入硬件配置, 也可以通过一定的逻辑优化来解决问题。

知识补充:(针对该现象)

  1. 内存中什么对象是永久代
    有时候把永生代和方法区对等, 方法区是多个线程共享的区域, 存储常量信息,类信息,方法信息。
截取自《深入理解java虚拟机 JVM高级特性与最佳实践》2.2.5
  1. JVM性能调优监控工具 使用
    往往大多数程序员忽视了这方面的知识, 对关于jvm的问题束手无策, 其实jdk中为我们提供了大量的jvm调优及监控工具, 比如jps、jstack、jmap、jhat、jstat。
    在本次我们使用了jps和jstat来查看问题, 当然这些命令还有其他参数,如果感兴趣的话可以在网上搜索。

针对CPU占用高的问题

系统CPU占用高曾经也出现过,所以很快能够排查出大致问题所在。

大致思路

1. 检查是哪个进程占用了高cpu

>  top              # top命令经常用来监控linux的系统状况
top命令示意图

有时候会看到mysql进程占用很高cpu
一般mysql的配置dba会配置好,往往不是mysql配置的问题, 所以 对于开发人员来说, 首先看慢sql日志。如果此时发现有大量慢sql日志产生, 则需要结合实际业务场景进行相应的sql及逻辑优化, 有必要的话可以通过一些缓存手段来解决问题。

如果是java 应用占用很高cpu

2 java应用CPU占用高

这时候我们开始对具体的应用进行分析了, 我们可以借用一些工具来分析java进程。如
jstack、jmap、jhat、hprof。

我的做法是首先定位占用高cpu的线程:
步骤如下:

  1. 通过jps获取进程id
  2. 通过jstack 查找线程dump
>  ps -mp pid  -o THREAD,tid,time
线程
将线程id转换为16进制(以方便找到dump中对应的线程)
> printf "%x\n" tid
>  jstack pid |grep tid -A 60      这里的tid为转换的16进制, grep -A  n 为匹配的行数后n条

查询结果大致如下:

"container-0" prio=10 tid=0x00007f9a14e1e800 nid=0x465a waiting on condition [0x00007f9a6dc57000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
    at java.lang.Thread.sleep(Native Method)
    at org.apache.catalina.core.StandardServer.await(StandardServer.java:427)
    at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer$1.run(TomcatEmbeddedServletContainer.java:177)
"VM Thread" prio=10 tid=0x00007f9a7812f800 nid=0x45ec runnable 
"GC task thread#0 (ParallelGC)" prio=10 tid=0x00007f9a7801e000 nid=0x45dd runnable 

如果定位发现cpu高的线程为GC, 很有可能是GC出现了问题。
如果线程dump中执行的是某业务代码, 可能是发生了死循环之类的。

参考:
[1] jstat 命令详解
[2] Java SE Specifications Chapter 2. The Structure of the Java Virtual Machine
[3] 《深入理解java虚拟机 JVM高级特性与最佳实践》

相关文章

  • GC 永久代溢出导致服务宕机

    现象 今天, 生产上的springboot 应用cpu 达到200%, 即占用了2核, 线上应用奔溃, 应用无法访...

  • Android内存优化—内存优化总结

    内存问题 内存抖动:导致GC导致卡顿 内存泄漏:导致频繁GC,可用内存减少 内存溢出:导致OOM 工具排查 AS中...

  • java GC详解

    工作中出现的内存溢出异常, 最后只需要调节相应内存大小即可。 永久代内存溢出实例永久代内存溢出实例 jvm各参数含...

  • 记录一次服务器宕机分析过程(2)-深入Lua GC

    继续接着上一篇文章记录一次服务器宕机分析过程(1)-排查问题分析宕机问题 Lua GC算法 Lua GC实现的是一...

  • java GC

    Full GC 就是收集整个堆,包括新生代,老年代,永久代(在JDK 1.8及以后,永久代会被移除,换为metas...

  • 美团+头条+蚂蚁金服面试十五问+PDF文档

    美团面试十五问 1. java虚拟机内存模型 2. 内存溢出一般发生在哪个区?永久代会不会导致内存溢出? 3. 动...

  • Java OutOfMemoryError 宕机实验

    概述 JVM OutOfMemoryError(OOME,内存溢出错误)导致宕机的情况有多种,此处主要以超出堆最大...

  • JVM GC知识(二)- HotSpot 垃圾回收器

    Sun HotSpot垃圾回收器 概览 新生代和老年代用到的一些垃圾回收器 永久代 当永久代和老年代触发 GC 时...

  • Android 内存优化工具介绍

    一、内存优化介绍 内存问题:内存抖动:锯齿状、GC 导致卡顿内存泄漏:可用内存减少、频繁GC内存溢出:OOM、程序...

  • 二. Android 内存优化

    1. 内存问题: 内存抖动(锯齿状、GC导致卡顿)内存泄漏:可用内存减少、频繁GC内存溢出:OOM、程序异常 2....

网友评论

      本文标题:GC 永久代溢出导致服务宕机

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