系统宕机,内存溢出等典型问题排查思路及工具使用
问题范围:平台典型后端问题,如宕机、服务响应慢、节点丢失、CPU高、内存高、数据库响应慢等。分析这类问题虽然没有固定套路,但是有大概方向。
工具范围:平台自带服务质量监控、堆分析工具、线程分析工具、arthas、visualvm、zabbix监控等。分析内存问题(OOM、GC)首先要建立JVM内存知识结构。
以下以JDK8和CMS GC为标准
问题
宕机
分析jvm crash文件
-
检查工作目录(%AWS_HOME%/bin,优先检查)或系统临时目录下,是否有hs_err_pid{pid}.log格式的文件
-
临时目录位置:windows:C:\Windows\Temp,macos: echo $TMPDIR,linux:/tmp
-
-
分析方式1:用文本编辑器打开此文件
-
典型问题1:windows下,sla的的sigar组件兼容性不好。
-
典型问题2:OOM异常,需要继续分析heap dump,见「OOM问题」
-
-
分析方式2:用在线工具https://fastthread.io/打开,格式化展示,可以作为协助。
OOM
平台常遇到的2类OOM,可能引起宕机,也可能不会。
-
最常见:java.lang.OutOfMemoryError: Java heap space
-
原因:堆空间已满,且GC之后无法腾出更多空间
-
线索来源
-
日志文件
-
crash文件
-
%AWS_HOME%/logs目录下产生了hprof后缀的文件
-
-
确定问题
-
需分析heap dump文件,见「工具-MAT」章节
-
-
-
其次:java.lang.OutOfMemoryError: Metaspace
-
原因:加载到内存中的class的数量或体积太大导致
-
增大aws_startup.sh的-XX:MetaspaceSize=1024m -XX:MaxMetaspaceSize=1024m为2048m即可,一般情况下1024足够,除非安装的应用特别多
-
集群节点不可用/集群节点丢失
此类未造成OOM但服务不可用问题相对宕机来讲,更难定位,因为宕机后有明显线索。
-
线索来源
-
后台切换节点切换不过去
-
集群节点反复丢失/加入
-
页面提示xx节点不可用
-
或者提示:同步出错,请重试
-
-
原因
-
绝大部分原因是由于GC停顿时间过长导致,解决方式见「问题-服务响应慢-GC时间过长」章节
-
极少情况是网络抖动导致
-
-
确定问题
-
在系统响应慢时,执行命令导出heap dump,分析内存中有哪些对象导致GC慢
-
分析heap dump见「工具-MAT」章节
-
服务响应慢
观察SLA >3秒的线程,如果:
-
单个请求慢,查看堆栈确定问题原因
-
等待数据库返回
-
优化SQL,添加索引等
-
如果是流程表/任务表数据量很大(千万以上)可以考虑分库分表(SAD应用)
-
-
其他如等待网络返回,需要具体情况具体分析
-
-
整个平台响应慢
-
优先考虑大量对象进入内存导致或其他代码漏洞导致GC时间过长
-
实时查看GC时间是否过长,见「工具-jstat」章节
-
统计查看GC时间是否过长
-
开启jvm的GC参数,会在相应目录下产生gc文件
-
用工具分析GC时间,见「工具-gc日志分析」章节
-
-
CPU使用率高
需要安装监控工具监控CPU使用情况,持续>80%时,就要分析是正常业务还是代码Bug。
-
正常情况:从SLA观察并发线程数很多,且请求响应时间尚可,可以考虑增加CPU资源。
-
异常情况1:从SLA观察到的并发线程数并不多,但CPU持续高位运行。
-
关注>3秒的线程堆栈
-
用jvisualvm对cpu采样分析,见「工具-jvisualvm」章节
-
-
异常情况2:频繁GC造成
-
可用jstat工具查看GC情况,见「工具-jstat」章节
-
此类情况需要分析是正常业务对象还是代码漏洞,前者增大堆内存即可(-Xmx和-Xms),后者需要导出dump分析对象情况,见「工具-MAT」
-
无法创建线程
报错java.lang.OutOfMemoryError: unable to create new native thread
-
原因:创建线程太多,已超过操作系统能承载的最大数量。
-
线程池使用错误导致创建太多线程
-
慢请求导致线程持续累积(慢请求原因很多,可从sla >3秒的线程堆栈寻找线索)
-
系统压力确实太大,需要增加CPU和内存配置
-
-
分析:导出thread dump(命令:jstack -l pid),分析:见「工具-fastthread.io」
工具
Memory Analyzer (MAT)
-
关注点1(重点):Leak Suspects部分
-
大多数时候,是由于查询大量数据库数据进入内存导致,可能是平台Bug,也可能是二开代码。此部分如何在日常运维中预防,见「运维监控-数据库」章节
-
-
关注点2:对象直方图,按照Retained Heap(该类对象hold住的内存大小)排序,可以分析对象是合理的cache还是bug产生的大量对象
-
关注点3:线程情况,按照Retained Heap(该线程hold住的内存大小)排序,关注前几个hold住大对象的线程
-
MAT能展示的信息非常多,可以以各种角度分析对象情况,甚至可以用OQL语句(类似SQL)过滤查询每个对象的数量
fastthread.io
该网站主要用来分析线程情况,会以各种视角展示线程。也可以分析crash日志(见「问题-宕机」部分)
-
关注点1:总的线程数(1500以上就值得警惕,如果是>2000,基本可以断定有问题)
-
线程绝对不是越多越好,尤其注意server.xml里的maxClient配置,一般出厂默认的800就足够大了。
-
-
关注点2:线程分组后的线程数,某类线程过多,需要根据实际情况排查
-
关注点3:相同堆栈的线程
-
关注点4:死锁。二开多线程编程较少,此类情况不常见。
jstat
使用jstat命令,可以分析内存各区域的变化情况以及GC的时间,如图中可以得到一下信息
-
年轻代和老年代均处于爆满情况(99%和100%)
-
单次GC停顿时间非常长,FGCT/FGC=11秒左右(一般500毫秒以下为合理值)
jvisualvm
jvisualvm是windows或mac版jdk自带的图形分析工具
-
可通过jmx或jstatd连接远程服务器,参考jvisualvm监控远程jvm的两种连接方式对比
-
查看CPU、堆和线程的概览
-
查看线程的实时运行情况
-
可对CPU进行抽样分析,找到消耗CPU的方法(可具体到线程和方法级别)
-
可对内存进行抽样分析,找到大对象
GC日志分析
-
优先:https://gceasy.io/
-
重点关注GC停顿时间,集群节点通信timeout时长3秒,GC超过这个时间就会节点丢失
-
-
其次:客户端软件:GC Viewer
日志链路追踪
平台的链路非常短,默认只有web -> app
-
如果怀疑是某个web服务导致的问题,可以通过结合web日志和app日志的traceId判断是否是同一请求
运维监控
系统交付客户使用时,需要给客户同步相关运维知识,尤其是监控和告警机制。随着时间推移,数据库数量增大、业务应用增多后,可能出现意想不到的问题。需要相应的监控巡检和告警机制,提前对系统进行人工干预或者排查问题。
IaaS资源
-
需要对IaaS层面资源,如CPU使用率、CPU负载、内存、网络、IO等进行监控和告警通知。
-
Web服务器、APP服务器、和数据库服务器、甚至是网关均需要。
服务质量监控(SLA)
SLA是用同进程Java统计运行情况,当JVM运行压力小时,可有效统计,运行压力大时,可供参考。
-
巡检关注1:>3秒的线程,此处太慢轻则影响用户体验,严重累积则导致系统不可用/宕机。
-
点击时间按钮打开堆栈,分析慢的原因。可能是慢sql、请求外部接口、处理大量数据等。
-
线程卡住之后,只能重启平台解决,无法kill掉线程。(强行kill可能导致资源泄露或其他不可控问题,java已废弃线程的stop方法)
-
-
巡检关注2:Top5线程,系统启动以来最慢的5个线程,可能线程已经运行结束,所以无法查看堆栈,所以只能提供线索。
-
巡检关注3:SQL返回条数告警(6.4.3以后),默认>1W告警。返回行数太多时,容易造成GC停顿时间过长甚至是OOM错误。同数据库返回条数监控,需要配合使用,区别:
-
优点:AWS平台可以记录下调用SQL的位置(有详细堆栈)
-
缺点:一次性返回超出JVM heap承受的数据时,会造成JVM宕机,从而无法记录该事故。
-
Java
JVM监控工具有多种,蓝鲸或zabbix使用居多。
-
巡检关注1:heap使用率。app server默认在heap达到配置的75%时进行FullGC(受参数-XX:CMSInitiatingOccupancyFraction控制),如果heap使用率连续若干分钟均处于75%以上运行,则需要导出heap dump进行分析,此时可能有内存泄露。
-
巡检关注2:GC时间,GC过慢会影响系统运行。
数据库
数据库监控工具有多种,蓝鲸或zabbix使用居多,或者用自带命令分析log文件,每家客户的手段不太一样。
-
巡检关注1:返回条数>1W的数据,思路同SLA中的SQL返回条数告警,需要配合使用,区别:
-
优点:不受Java服务器宕机影响,理论上可记录所有事故SQL
-
缺点:只能记录SQL,无法准确判断AWS的调用代码位置,需要根据经验去排查平台。
-
-
巡检关注2:慢SQL。此类SQL会影响用户体验,增大Java服务器并发压力,严重的话会导致大量请求积累,从而导致宕机。(所以需要巡检关注SLA的>3秒的线程)
结束语
对于系统性问题的思考、理解,以上只是抛砖引玉,需要不断学习实践总结。比如MAT的各种对象信息、zabbix的各种jvm监控指标含义等。 寻找解决方案时,强烈建议google,效率n倍加(可以用翻译软件)