一、发现问题

下面是线上机器的cpu使用率,可以看到从4月8日开始,随着时间cpu使用率在逐步增高,最终使用率达到100%导致线上服务不可用,后面重启了机器后恢复。

二、排查思路

简单分析下可能出问题的地方,分为5个方向:

1.系统本身代码问题

2.内部下游系统的问题导致的雪崩效应

3.上游系统调用量突增

4.http请求第三方的问题

5.机器本身的问题

三、开始排查

1.查看日志,没有发现集中的错误日志,初步排除代码逻辑处理错误。

2.首先联系了内部下游系统观察了他们的监控,发现一起正常。可以排除下游系统故障对我们的影响。

3.查看provider接口的调用量,对比7天没有突增,排除业务方调用量的问题。

4.查看tcp监控,TCP状态正常,可以排除是http请求第三方超时带来的问题。

5.查看机器监控,6台机器cpu都在上升,每个机器情况一样。排除机器故障问题。

即通过上述方法没有直接定位到问题。

四、解决方案

1.重启了6台中问题比较严重的5台机器,先恢复业务。保留一台现场,用来分析问题。

2.查看当前的tomcat线程pid

3.查看该pid下线程对应的系统占用情况。top -Hp 384

4.发现pid 4430 4431 4432 4433 线程分别占用了约40%的cpu

5.将这几个pid转为16进制,分别为114e 114f 1150 1151

6.下载当前的java线程栈  sudo -u tomcat jstack -l 384>/1.txt

7.查询5中对应的线程情况,发现都是gc线程导致的

8.dump java堆数据

sudo -u tomcat jmap -dump:live,format=b,file=/dump201612271310.dat 384

9.使用MAT加载堆文件,可以看到javax.crypto.JceSecurity对象占用了95%的内存空间,初步定位到问题。

MAT下载地址:http://www.eclipse.org/mat/

10.查看类的引用树,看到BouncyCastleProvider对象持有过多。即我们代码中对该对象的处理方式是错误的,定位到问题。

五、代码分析

我们代码中有一块是这样写的

这是加解密的功能,每次运行加解密都会new一个BouncyCastleProvider对象,放倒Cipher.getInstance()方法中。

看下Cipher.getInstance()的实现,这是jdk的底层代码实现,追踪到JceSecurity类中

verifyingProviders每次put后都会remove,verificationResults只会put,不会remove.

看到verificationResults是一个static的map,即属于JceSecurity类的。

所以每次运行到加解密都会向这个map put一个对象,而这个map属于类的维度,所以不会被GC回收。这就导致了大量的new的对象不被回收。

六、代码改进

将有问题的对象置为static,每个类持有一个,不会多次新建。

七、本文总结

遇到线上问题不要慌,首先确认排查问题的思路:

  1. 查看日志
  2. 查看CPU情况
  3. 查看TCP情况
  4. 查看java线程,jstack
  5. 查看java堆,jmap
  6. 通过MAT分析堆文件,寻找无法被回收的对象

通过jstack与jmap分析一次cpu打满的线上故障的更多相关文章

  1. JAVA 线上故障排查套路,从 CPU、磁盘、内存、网络到GC 一条龙!

    线上故障主要会包括cpu.磁盘.内存以及网络问题,而大多数故障可能会包含不止一个层面的问题,所以进行排查时候尽量四个方面依次排查一遍. 同时例如jstack.jmap等工具也是不囿于一个方面的问题的, ...

  2. JVM 线上故障排查基本操作--CPU飙高

    JVM 线上故障排查基本操作 CPU 飚高 线上 CPU 飚高问题大家应该都遇到过,那么如何定位问题呢? 思路:首先找到 CPU 飚高的那个 Java 进程,因为你的服务器会有多个 JVM 进程.然后 ...

  3. 通过jstack与jmap分析一次线上故障

    一.发现问题 下面是线上机器的cpu使用率,可以看到从4月8日开始,随着时间cpu使用率在逐步增高,最终使用率达到100%导致线上服务不可用,后面重启了机器后恢复. 二.排查思路 简单分析下可能出问题 ...

  4. jstack与jmap分析java堆栈信息

    首先确定要查询的服务进程pid,可用ps -ef|grep 进程名称 jstack -l pid >> stack_info.txt,将此进程的堆栈信息导出到txt文件中 其中" ...

  5. 由一次线上故障来理解下 TCP 三握、四挥 & Java 堆栈分析到源码的探秘

    本文导读: 生产故障场景介绍 TCP 建连三次握手过程 TCP 断连四次挥手过程 结合 Java 堆栈剖析源码 再从堆栈中找到"罪魁祸首" 问题优化方案总结 1.生产故障场景介绍 ...

  6. 排查Java线上服务故障的方法和实例分析

    前言 作为在线系统负责人或者是一个技术专家,你可能刚刚接手一个项目就需要处理紧急故障,或者被要求帮忙处理一些紧急的故障,这个时候的情景是: (1)你可能对这个业务仅仅是听说过,而不怎么真正了解: (2 ...

  7. Java线上问题排查思路及Linux常用问题分析命令学习

    前言 之前线上有过一两次OOM的问题,但是每次定位问题都有点手足无措的感觉,刚好利用星期天,以测试环境为模版来学习一下Linux常用的几个排查问题的命令. 也可以帮助自己在以后的工作中快速的排查线上问 ...

  8. 线上bug分析

    昨天下午大神把组内几十号人召集在一起开Online bug分析大会,主要是针对近期线上事故从事故原因和解决方案两个维度来分析. 对金融软件来说,每一次的线上事故都有可能给公司带来重大的损失,少扣了用户 ...

  9. JVM性能调优监控工具jps、jstack、jmap、jhat、jstat、hprof使用详解

    摘要: JDK本身提供了很多方便的JVM性能调优监控工具,除了集成式的VisualVM和jConsole外,还有jps.jstack.jmap.jhat.jstat.hprof等小巧的工具,本博客希望 ...

随机推荐

  1. H5学习之旅-H5的框架(13)

    H5框架语法介绍 :frame:框架对于页面的设计有很大的作用 frameSet:框架集标签定义如何将窗口分割为框架 ,每一个frameset定义一些列行或者列,rowS/COLS规定了每行或者每列占 ...

  2. 算法面试题-leetcode学习之旅(一)

    问题描述 Given an array of size n, find the majority element. The majority element is the element that a ...

  3. 【一天一道LeetCode】#29. Divide Two Integers

    一天一道LeetCode系列 (一)题目 Divide two integers without using multiplication, division and mod operator. If ...

  4. Adobe Audition 基本使用

    1.1简介 Adobe Audition (前身是Cool Edit Pro) 是Adobe公司开发的一款功能强大.效果出色的多轨录音和音频处理软件.它是一个非常出色的数字音乐编辑器和MP3制作软件. ...

  5. hive:(group by, having;order by)的使用;group by+多个字段,以及wiki说的group by两种使用限制验证

    hive> select * from app_data_stats_historical where os='1' group by dt limit 100; 出现结果如下: 2014-01 ...

  6. 苹果新的编程语言 Swift 语言进阶(七)--枚举、结构、类

    Swift语言中,具有类特征的类型包括三种,即枚举类型.结构类型(包括基本类型,基本类型实际都是结构类型的特例).类.其中枚举类型.结构类型是属于值类型,类属于引用类型.三种类型都可以添加属性.方法. ...

  7. ExtAspNet页面跳转的方法

    一:如果在Page_Load中则可以用Response.Redirect("ABC.aspx"); 二:在其它事件中可以用以下方法: protected void Button1_ ...

  8. C语言之linux内核实现最大公约数算法

    最大公约数算法,又称欧几里德算法,至今已有几千年的历史了.在我们开始学习C语言的时候最常用的算法就是辗转相除法,其实在linux内核中,内核也是使用这样的方法实现两数最大公约数的计算. 两个整数的最大 ...

  9. 如何利用c中的指针实现两个8bit的数合并为16bit

    对于从事单片机开发,进行单片机c语言开发的人来说,在对外部信息采集回来的数据进行处理,经常会用到,将采集到的第一个字节作为高8位,采集到的第二个字节作为低8位,从而构成1个16bit的数,得到一次完整 ...

  10. async & await 异步编程的一点巧方法

    await 关键字不会创建新的线程,而是由Task任务或是FCL中的xxxAsync等方法创建的线程,而且这里创建的线程都是基于线程池创建的工作线程,属于后台线程. await关键字会阻塞/暂停调用它 ...