快速定位java系统的线上问题--转
原文地址:http://m.blog.csdn.net/article/details?id=43376943
前言:我们的场景并没有像BAT等大型互联网公司里的系统那么复杂,但是基本上也有一定的规模,暂且就认为我们是一个中型互联网系统。但是工具和思路都是差不多的,因为原理是一样的。同时下面提到的命令,具体详细的用法,我想google上已经有足够多的资源了,这里只说思路与方向。
首先我们分析一下服务器构造和操作系统,服务器我们可以简单的分解为CPU、内存、硬盘(其他部件的我们就不考虑了),操作系统:我们简单的认为操作系统是来协同上面说的CPU、内存、硬盘的一个系统,然而jdk bin目录里的应用程序最后都会运行在操作系统上,所以jdk会借助操作系统来操作CPU、内存、硬盘。 所以常见的线上问题,通常就出现在CPU、内存、硬盘和操作系统这个几个维度上。
这里总结一下我所碰到过的问题:CPU 利用率高、内存溢出、应用程序很卡(但是又没挂)、各种诡异问题(很难重现但总是偶尔出现)等。
首先我们来说内存,因为通常内存问题是最经常出的,常见的有内存溢出(OOM)、GC问题等。排查这些问题需要了解linux相关命令:
top 后,shift + m 来对各进程按内存进行排序
free 查看linux整体内存情况
OOM异常最好排查,因为已经溢出报错了,常用解决办法:
jmap 导出内存堆栈信息,并用第三方工具(比如MAT)分析,这些工具基本上可以展示到底是哪种对象最多。(这种是最常用的方法)
第三方工具在线展现具体的堆栈信息,比如:https://github.com/alibaba/TBJMap
(我并没有实际用过,但是淘宝开源的一定是他们实际用过的,但是一般此类工具最好还是在测试环境中使用)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利用率过高。总结一下我们碰到过的有以下几中:
的确计算量过大,cpu运算不过来
IO读写过于频繁
java线程竞争锁过于频繁
应用程序很卡(但是又没挂)
要排查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,阿里系也在使用,我想应该是靠谱的。他们的原理就是在线上运行的代码上动态的编织一些“料”进去,并能抽取其中一些结果来给调试者提供信息。
不过我的实践经验通常诡异问题是因为一些小细节的疏忽,或者一些低级错误。然后找到恨不得抽自己三个嘴巴。所以对原理的理解才能写出更好的代码。
其他碰到过的问题:
因为linux文件系统权限的问题,导致某些框架没有读权限,抛异常,而此类异常有的时候不是直接提示没有权限,比如有的可能会提示空指针异常,而这类问题去google通常是没有答案的。如果是空指针,那就好办了,去看源码。我想已经没有比空指针还好解决的问题了。
接下来我们总结一下,我们上面提到了下面这些关键词:
top
top -H -p (这个很有用)
jmap
tbjmap
jstack
jprofiler
jvisualvm
TProfiler
BTrace
HouseMD
java 线程状态
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系统的线上问题--转的更多相关文章
- Java架构师线上问题排查,这些命令程序员一定用得到!
Java架构师线上问题排查,这些命令程序员一定用得到! 线上问题排查,以下场景,你遇到过吗? 一.了解机器连接数情况 问题:1.2.3.4的sshd的监听端口是22,如何统计1.2.3.4的sshd服 ...
- 【重装系统】线上Linux服务器(2TB)分区参考方案
如果是线上服务器,假设它是 2TB 的 SATA 硬盘.8GB 内存,建议按如下方式进行分区: / 20480M(20G)(主分区) /boot 128M swap 10240M /data 2016 ...
- eclipse快速定位java对应的class
当前设置值,只能定位class文件 设置eclipse External Tools Configurations... Program --> new New 创建viewclass.bat文 ...
- Linux系列(2):入门之线上求助
前言:Linux命令那么多,你是否为记不住Linux的命令而烦恼呢? 这一章节就是来解决这个问题的. 1.Linux系统的线上求助 1.指令补全 在上一章节提到过使用[Tab]快捷键可以根据用户输入的 ...
- 用“逐步排除”的方法定位Java服务线上“系统性”故障(转)
一.摘要 由于硬件问题.系统资源紧缺或者程序本身的BUG,Java服务在线上不可避免地会出现一些“系统性”故障,比如:服务性能明显下降.部分(或所 有)接口超时或卡死等.其中部分故障隐藏颇深,对运维和 ...
- Java线上问题排查神器Arthas快速上手与原理浅谈
前言 当你兴冲冲地开始运行自己的Java项目时,你是否遇到过如下问题: 程序在稳定运行了,可是实现的功能点了没反应. 为了修复Bug而上线的新版本,上线后发现Bug依然在,却想不通哪里有问题? 想到可 ...
- Arthas - Java 线上问题定位处理的终极利器
前言 在使用 Arthas 之前,当遇到 Java 线上问题时,如 CPU 飙升.负载突高.内存溢出等问题,你需要查命令,查网络,然后 jps.jstack.jmap.jhat.jstat.hprof ...
- 从一次线上故障思考Java问题定位思路
问题出现:现网CPU飙高,Full GC告警 CGI 服务发布到现网后,现网机器出现了Full GC告警,同时CPU飙高99%.在优先恢复现网服务正常后,开始着手定位Full GC的问题.在现场只能够 ...
- 快速定位iOS线上BUG在哪个控制器崩溃
快速定位iOS线上App崩溃在哪个控制器里面,需要和后台配合使用 下载本SDK并手动添加到项目里 新建所有的页面都继承于YZViewController 在AppDelegate的didFinishL ...
随机推荐
- shell学习日志
0.shell的变量同环境变量不同,存在用户环境区. 变量赋值的方式是: variable_name = variable_value a= "hello" $a对a进行取值 关于 ...
- SpringBoot实战(四)获取接口请求中的参数(@PathVariable,@RequestParam,@RequestBody)
上一篇SpringBoot实战(二)Restful风格API接口中写了一个控制器,获取了前端请求的参数,现在我们就参数的获取与校验做一个介绍: 一:获取参数 SpringBoot提供的获取参数注解包括 ...
- 05004_Linux的其他命令和权限命令
1.其他命令 (1)显示当前所在位置 命令:pwd (2)搜索命令 a.命令:grep 要搜索的字符串 要搜索的文件 示例:搜索/etc/sudu.conf文件中包含字符串to的行 b.搜索/etc/ ...
- Web长连接推送
http://www.workerman.net/web-sender http://wahahachuang5.iteye.com/blog/2311313
- Qt之QImageReader
简述 QImageReader类为从文件或设备读取图像提供了一个独立的接口. 读取图像最常用的方法是通过构造QImage和QPixmap,或通过调用QImage::load()和QPixmap::lo ...
- Swift编写的一些完整的app
收集了一些实用swift编写的app,这些demo都是不错的值得学习的. 知乎日报 Swift-ZhihuDaily Swift版知乎日报 参照了YANGReal的糗事百科和uitableview的例 ...
- a+=b 等价于 a=a+b ?
a += b和a = a + b全然等价么(java)?可能非常多人以为是一样的,事实上并不是等价的,以下看一下证据吧. public class Test { public static void ...
- POJ 2739 Sum of Consecutive Prime Numbers(素数)
POJ 2739 Sum of Consecutive Prime Numbers(素数) http://poj.org/problem? id=2739 题意: 给你一个10000以内的自然数X.然 ...
- UVA 11825 - Hackers' Crackdown 状态压缩 dp 枚举子集
UVA 11825 - Hackers' Crackdown 状态压缩 dp 枚举子集 ACM 题目地址:option=com_onlinejudge&Itemid=8&page=sh ...
- bzoj1026: [SCOI2009]windy数(传说你是数位DP)
1026: [SCOI2009]windy数 题目:传送门 题解: 其实之前年少无知的时候好像A过...表示当时并不知道什么数位DP 今天回来深造一发... 其实如果对这个算法稍有了解...看到这题的 ...