原文地址:http://m.blog.csdn.net/article/details?id=43376943

前言:我们的场景并没有像BAT等大型互联网公司里的系统那么复杂,但是基本上也有一定的规模,暂且就认为我们是一个中型互联网系统。但是工具和思路都是差不多的,因为原理是一样的。同时下面提到的命令,具体详细的用法,我想google上已经有足够多的资源了,这里只说思路与方向。

首先我们分析一下服务器构造和操作系统,服务器我们可以简单的分解为CPU、内存、硬盘(其他部件的我们就不考虑了),操作系统:我们简单的认为操作系统是来协同上面说的CPU、内存、硬盘的一个系统,然而jdk bin目录里的应用程序最后都会运行在操作系统上,所以jdk会借助操作系统来操作CPU、内存、硬盘。 所以常见的线上问题,通常就出现在CPU、内存、硬盘和操作系统这个几个维度上。

这里总结一下我所碰到过的问题:CPU 利用率高、内存溢出、应用程序很卡(但是又没挂)、各种诡异问题(很难重现但总是偶尔出现)等。

首先我们来说内存,因为通常内存问题是最经常出的,常见的有内存溢出(OOM)、GC问题等。排查这些问题需要了解linux相关命令:

  1. top 后,shift + m 来对各进程按内存进行排序

  2. free 查看linux整体内存情况

OOM异常最好排查,因为已经溢出报错了,常用解决办法:

  1. jmap 导出内存堆栈信息,并用第三方工具(比如MAT)分析,这些工具基本上可以展示到底是哪种对象最多。(这种是最常用的方法)

  2. 第三方工具在线展现具体的堆栈信息,比如:https://github.com/alibaba/TBJMap
    (我并没有实际用过,但是淘宝开源的一定是他们实际用过的,但是一般此类工具最好还是在测试环境中使用)

  3. jprofiler、jvisualvm(具体怎么用,请google)

上面的几种工具和思路,已经基本能搞定OOM类型的问题了

GC问题:我们所碰到过的通常会因为GC回收过于频繁导致CPU过高,或者因为fullgc让整个java进程暂停。此类问题可以借助 jstat -gcutil pid查看各个区域和gc相关信息。当然一些在线工具(jprofiler、jvisualvm)也可以查看,但是不推荐线上使用,jstat已经很NB了。至于里面具体每个字段什么意思,google上已经非常多了。通常查jstat + jmap分析已经基本上能让你知道,是哪个地方的内存问题引起了GC问题。

但是,jstat上会出来很多信息,这里需要对java的内存管理有一定的了解,至少得知道,堆栈、分代机制、新生代、老生代等相关区域有一定的了解。总之要解决内存问题,得对java里的内存要了解。

CPU问题会相对来说复杂很多,CPU好比服务器的大脑,很多其他的组件也可能会导致CPU利用率过高。总结一下我们碰到过的有以下几中:

  1. 的确计算量过大,cpu运算不过来

  2. IO读写过于频繁

  3. java线程竞争锁过于频繁

  4. 应用程序很卡(但是又没挂)

要排查CPU相关的问题,首先得了解linux的top命令,top的功能非常多,具体每个属性什么意思请先google一下。

解决CPU类的问题总体思路:找到java进程中哪些线程使用CPU很高,简单的说就是top -H -p pid,这个命令会出现java进程里哪些线程使用CPU很高,会按降序排序,但是子线程编号与jstack pid 里出来的不太一样,jstack里出来的是16进程,所以把top -H -p里的转成16进程,然后查找一下具体的线程。

1.的确计算量过大,cpu运算不过来

通过上面的top -H -p和 jstack基本已经能看出来这种类型的问题

2.IO读写过于频繁

截图中的wa。这个代表是cpu等待io的时间,简单的说就是io正在处理,告诉cpu请等我一下,我处理完了就让你去干别的。因为cpu是固定资源,它被io所持有,那么别人就没有办法使用,所以就导致cpu使用率上去了。所以io wait很高就思路很清楚了,接下来就要去查看具体哪些线程在频繁操作io。

接下来就用jstack pid 来查看具体jdk中具体线程,先扫一眼,看是否有很多线程都处于io操作的阶段。但是这还不能完全解决问题,有的时候信息太多,实在不好找,一眼眼看,要看得头痛。所以简单点也可以使用第1点里提到的方法。

3.java线程竞争锁过于频繁

top -H -p和 jstack已经基本上能看出,但是这里还需要对java 线程的各种状态要了解一下。要能理解jstack出来的线程信息里每种状态是什么含义。这样才能分析出具体原因,不然跑去看代码总感觉不应该啊,应该没错啊。

4.应用程序很卡(但是又没挂)

这类问题如果业务不是很复杂,基本上用top -H -p 和 jstack可以查看得出来。但是有的时候还不能完全确定,一种常见的办法就是打日志,这种办法当然是OK的。但是这里再介绍一些可以直接在线上就能定位和分析的工具。https://github.com/alibaba/TProfiler,号称是可以线上使用的分析工具,淘宝开源的东西我们已经使用过很多了,基本上是靠谱的。

各种诡异问题:

所谓诡异问题,通常是飘忽不定,偶然出现,又难重现,搞得人非常想砸电脑的问题。但是它又的确出现了,我一直强调这个世界是科学的,碰到jvm编译器级别的BUG,我想有,但是可能不是你的这次案例,所以不要轻易怀疑是jvm的问题,我想不是像BAT等一些非常大型的系统很难碰到编译器级别的问题。

那么碰到这种问题不好重现,一种就是打日志,通过日志来排查程序运行的逻辑,比如一些多线程引起的逻辑问题。如果打日志太麻烦,而且又要重启很多东西,那么就可能要搬出神器来了,这里介绍两种(虽然两种都没有线上用来解决过实际问题,但按原理介绍应该是种解决问题的思路,毕竟不可能每种工具用过,了其原理就可以来判断是否能为己所用),第一种是BTrace、第二种是HouseMD(号称比BTrace更好用的工具)https://github.com/CSUG/HouseMD/wiki/UserGuideCN,阿里系也在使用,我想应该是靠谱的。他们的原理就是在线上运行的代码上动态的编织一些“料”进去,并能抽取其中一些结果来给调试者提供信息。

不过我的实践经验通常诡异问题是因为一些小细节的疏忽,或者一些低级错误。然后找到恨不得抽自己三个嘴巴。所以对原理的理解才能写出更好的代码。

其他碰到过的问题:

  1. 因为linux文件系统权限的问题,导致某些框架没有读权限,抛异常,而此类异常有的时候不是直接提示没有权限,比如有的可能会提示空指针异常,而这类问题去google通常是没有答案的。如果是空指针,那就好办了,去看源码。我想已经没有比空指针还好解决的问题了。

接下来我们总结一下,我们上面提到了下面这些关键词:

  1. top

  2. top -H -p (这个很有用)

  3. jmap

  4. tbjmap

  5. jstack

  6. jprofiler

  7. jvisualvm

  8. TProfiler

  9. BTrace

  10. HouseMD

  11. java 线程状态

  12. java 内存管理

每一种类型的都用过一次已经不错了,每一种类型的都在线上真实的排查过用过,那就更不错了,不过线上有这么多的问题也够严重的了。如果每一种工具和类型的问题都对其背后的工具和原理实践过、学习过,我想功力已经非常不错了。所以碰到每一个线上问题,都要有能够发散的思路,并能深入下去。而不是停留在工具这个层面。

工具上面已经介绍很多了,但是真正的场景中不可能每个去试,等试完所有的已经不叫快速了,通常做一个系统,会大致了解这个系统是IO密集型还是计算密集型应用,或者在开发的过程就已经知道了未来可能哪些地方会有增长。

通常出问题了,先上去看log4j和tomcat的日志,如果日志里能体现问题在哪里基本就到这里了,如果日志正常。那么通常是应用比较慢,那么先top。如果机器load高,找到CPU占用最高的进程。如果是java进程,可以先jstack 看个大概,如果还没有头绪, 就同时看一下GC情况,这时就要用jstat,gc正常,那就再用top -H -p,找CPU最高的地方。这么一套流程跑下来基本上能定位问题。如果load不高,那么情况就要复杂很多,要检查一些外围组件。

1、DB,看是不是很多SQL积压。如果sql也正常,别的表象都正常,那么就要利用类似TProfiler类似的工具(前提是你已经预先就部署好了)。

2、http,linux连接数是否很多,当前网络流量是不是跑满了,甚至我还碰到过某个http api所对应的域名dns有问题 ping 一下要几百ms。(淘宝还有网卡跑满的情况。。)

3、第三方本地应用慢,有的时候会使用一些linux上的工具,比如图片压缩。这些应也可能会影响程序。

上面的是我的常用思路和方法,但是具体的情况会有变化,比如我们现在在用的是阿里云的ECS,一台机器只有5M,所以带宽我会优先观察,如果带宽正常再看面的,所以具体的思路和方法还是要看对系统和当时的环境有多了解,需要做一些调整。

那让我们继续带着问题发散下去,接下来我们准备一些问题。

1、通常jstack 后 出来的线程堆栈信息后,再去top -H -p(或者反过来也可以)。中间总有时间差,可能jstack里的那个线程与top -H -p中出来的 那个已经对不上了。那这样可能并不能真实的反应实际情况。(当然通常是OK的)。那么有没有办法可以快速的来一个命令就能出来对应的线程?当然没有,那么没有就自己想原理能不能写嘛。这里应该有很多种办法可以做,比如可以通过shell把几个命令组合在一起,然后抽取对应的信息,然后分析,如果shell太复杂了,也可以用perl、python甚至java写一个linux上的小程序也是OK的啊。这样执行一个命令就可以快速的得到所有信息。再发散下去,有的时候不是每台机器都要登录上去,那能不能在某台特定的机器,甚至在自己的电脑上就可以去查看呢?是否可以做成网页,直接在浏览器上查看?

2、当出现问题后我们上去机器查看具体问题,我们认为自己是在拉信息,那么是否可以改成推模式?快有问题时推送数据到某个地方,说俗点就是监控和预警,那么我们使用的tomcat、jetty等容器是否可以在线监控?是否有预留接口?那要收集所有机器上的信息到同一个地方具体又有哪些解决方案。方案有一万种,全在google和基础原理中。

3、如果要做监控,那么怎么快速又灵活的添加监控项目,同时监控又不过于影响和侵入线上的业务,中间又有很多问题需要解决。

我想如果应用不是非常复杂,上面的这些方法和思路,基本上已经能解决绝大多数的问题了。

最后,我想线上问题最好的情况应该是被监控发现,就算要上去调试,用工具会比人手快,比如jstack 和 top -H -p用脚本去自动抽取top N最消耗CPU的子线程。

快速定位java系统的线上问题--转的更多相关文章

  1. Java架构师线上问题排查,这些命令程序员一定用得到!

    Java架构师线上问题排查,这些命令程序员一定用得到! 线上问题排查,以下场景,你遇到过吗? 一.了解机器连接数情况 问题:1.2.3.4的sshd的监听端口是22,如何统计1.2.3.4的sshd服 ...

  2. 【重装系统】线上Linux服务器(2TB)分区参考方案

    如果是线上服务器,假设它是 2TB 的 SATA 硬盘.8GB 内存,建议按如下方式进行分区: / 20480M(20G)(主分区) /boot 128M swap 10240M /data 2016 ...

  3. eclipse快速定位java对应的class

    当前设置值,只能定位class文件 设置eclipse External Tools Configurations... Program --> new New 创建viewclass.bat文 ...

  4. Linux系列(2):入门之线上求助

    前言:Linux命令那么多,你是否为记不住Linux的命令而烦恼呢? 这一章节就是来解决这个问题的. 1.Linux系统的线上求助 1.指令补全 在上一章节提到过使用[Tab]快捷键可以根据用户输入的 ...

  5. 用“逐步排除”的方法定位Java服务线上“系统性”故障(转)

    一.摘要 由于硬件问题.系统资源紧缺或者程序本身的BUG,Java服务在线上不可避免地会出现一些“系统性”故障,比如:服务性能明显下降.部分(或所 有)接口超时或卡死等.其中部分故障隐藏颇深,对运维和 ...

  6. Java线上问题排查神器Arthas快速上手与原理浅谈

    前言 当你兴冲冲地开始运行自己的Java项目时,你是否遇到过如下问题: 程序在稳定运行了,可是实现的功能点了没反应. 为了修复Bug而上线的新版本,上线后发现Bug依然在,却想不通哪里有问题? 想到可 ...

  7. Arthas - Java 线上问题定位处理的终极利器

    前言 在使用 Arthas 之前,当遇到 Java 线上问题时,如 CPU 飙升.负载突高.内存溢出等问题,你需要查命令,查网络,然后 jps.jstack.jmap.jhat.jstat.hprof ...

  8. 从一次线上故障思考Java问题定位思路

    问题出现:现网CPU飙高,Full GC告警 CGI 服务发布到现网后,现网机器出现了Full GC告警,同时CPU飙高99%.在优先恢复现网服务正常后,开始着手定位Full GC的问题.在现场只能够 ...

  9. 快速定位iOS线上BUG在哪个控制器崩溃

    快速定位iOS线上App崩溃在哪个控制器里面,需要和后台配合使用 下载本SDK并手动添加到项目里 新建所有的页面都继承于YZViewController 在AppDelegate的didFinishL ...

随机推荐

  1. SCIP,Clp,Gurobi和Cplex安装

    SCIP安装 1.在自己的家目录下建立目录scip,并将获得的压缩包考入该文件夹并解压缩 tar -zxvf scipoptsuite-5.0.0.tgz 2.进入目录scipoptsuite-5.0 ...

  2. vue-quill-editor-upload : 实现vue-quill-editor上传图片到服务器

    vue-quill-editor-upload git: https://github.com/NextBoy/vu... A plug-in for uploading images to your ...

  3. HDU 3108 Ant Trip

    Ant Trip Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Su ...

  4. Qt之自定义布局管理器(QFlowLayout)

    简述 QFlowLayout,顾名思义-流布局,实现了处理不同窗口大小的布局.根据应用窗口的宽度来进行控件放置的变化. 具体实现要求不再赘述,请参考前两节内容. 简述 实现 效果 源码 实现 QFlo ...

  5. iOS AES的加密解密

    主要是要得到加密后的原来的字符创,MD5无法得到原有的,仅仅能用AES+base64 要用GTMBase64这个能够自己去下载, 主要看另外2个类文件. #import <Foundation/ ...

  6. mysql-增删改数据

    一.增加操作 INSERT用来插入或添加行到数据库表的.插入用以下几种方式: 1.插入完整的行 insert into customers values(null,'Pep E,LaPew','100 ...

  7. 6、python中的字符串

    最早的编码为ascii码,共256个符号.UTF-8是国际通用编码,全面支持中文,以一个字节表示英文,以三个字节表示一个中文以及其他语言:GB2312是我国自己定制的中文编码标准,使用1个字节表示英文 ...

  8. SVN过滤设置

    为了方便管理我们的系统版本号.非常多人会用到SVN,开发中我们经经常使用到SVN插件, 可是对于某些文件的缓存来说, 我们仅仅要有操作缓存便会保存一次, 每次提交非常是麻烦, 可能有的文件或者目录我们 ...

  9. Canvas中的非零围绕规则原理

    非零围绕规则:对于路径中指定范围区域,从该区域内部画一条足够长的线段.使此线段的全然落在路径范围之外. 非零围绕规则计数器:然后,将计数器初始化为0,每当这个线段与路径上的直线或曲线相交时,就改变计数 ...

  10. 使用client对象模型读取SharePoint列表数据

    使用client对象模型读取SharePoint列表数据 client对象模型提供了强有力的方式.从远程client应用程序管理列表. 1. 管理员身份打开VS,新建项目Windows窗口应用程序,命 ...