所有的Java线上问题从系统表现来看无非归咎于这几种:CPU,内存,磁盘,网络。比如CPU突然飙升赞满,内存溢出,网络异常,磁盘爆满等问题。
一般我们先定位系统异常后再去定位到具体的业务异常,逐步进行排查。
2.1 系统异常排查流程图
系统异常排查流程图
2.2 业务异常排查流程图
1.查看日志,看有没有发现集中的错误日志,如果没有排除代码逻辑处理问题。
2.查看接口调用量问题,如果没有突增,排除业务调用量问题。
3.查看TCP监控,如果正常,排除请求第三方超时问题。
如果上述无法直接定位问题,那就只能逐一排除了。
3.1 CPU问题排查
首先我们通过top命令查看哪个进程的CPU使用率最高。
定位到高占用CPU进程后再使用 top -Hp pid 命令定位到具体是哪个线程。
将上一步获取到的线程id转换成16进制 printf '%x\n' pid 得到 nid。
之后我们需要使用 jstack pid |grep 'nid' -C5 –color 来查看上述进程中线程的堆栈信息。
找到对应线程的堆栈信息后看看具体是业务线程还是其他线程,比如gc线程。
也可以通过 cat jstack.log | grep "java.lang.Thread.State" | sort -nr | uniq -c 来查看一下线程状态,重点关注WAITING和TIMED_WAITING的线程,如果WAITING线程比较多那说明线程池分配有问题了。
3.2 内存问题排查
内存问题排查比CPU排查麻烦一些,问题场景比较多,主要包括OOM,GC等问题。可以先通过free命令来查看内存使用情况,找到占用内存高的进程。
内存使用情况
之后我们使用 jmap -dump:format=b,file=filename pid 来导出dump文件,通过mat导入dump文件进行分析,内存泄漏问题一般我们直接选Leak Suspects即可,mat给出了内存泄漏的建议。我们可以通过内存空间占用情况来慢慢分析具体是哪个类的问题。
mat软件
3.3 磁盘问题排查
首先我们使用 df -hl 来查看每个磁盘的使用情况。
之后我们想查看磁盘使用性能可以使用 iostat -d -k -x 来进行分析。下图中的最后一列%util可以看到每块磁盘写入的程度,而rrqpm/s以及wrqm/s分别表示读写速度,这样基本就能定位到是哪个磁盘出问题了。
遇到线上问题千万不要慌乱,先将程序恢复正常后再慢慢排查问题。分别查看日志,查看CPU情况,查看java线程,jstack,查看java堆,jmap,最后通过MAT分析堆文件,寻找无法被回收的对象,来找到代码层面的问题。