系统宕机,内存溢出等典型问题排查思路及工具使用

 
问题范围:平台典型后端问题,如宕机、服务响应慢、节点丢失、CPU高、内存高、数据库响应慢等。分析这类问题虽然没有固定套路,但是有大概方向。
工具范围:平台自带服务质量监控、堆分析工具、线程分析工具、arthas、visualvm、zabbix监控等。分析内存问题(OOM、GC)首先要建立JVM内存知识结构。
以下以JDK8和CMS GC为标准

问题

  宕机

    分析jvm crash文件
  • 检查工作目录(%AWS_HOME%/bin,优先检查)或系统临时目录下,是否有hs_err_pid{pid}.log格式的文件
    1. 临时目录位置:windows:C:\Windows\Temp,macos: echo $TMPDIR,linux:/tmp
  • 分析方式1:用文本编辑器打开此文件
    1. 典型问题1:windows下,sla的的sigar组件兼容性不好。
    2. 典型问题2:OOM异常,需要继续分析heap dump,见「OOM问题」
  • 分析方式2:用在线工具https://fastthread.io/打开,格式化展示,可以作为协助。

  OOM

    平台常遇到的2类OOM,可能引起宕机,也可能不会。
  • 最常见:java.lang.OutOfMemoryError: Java heap space
    1. 原因:堆空间已满,且GC之后无法腾出更多空间
    2. 线索来源
      1. 日志文件
      2. crash文件
      3. %AWS_HOME%/logs目录下产生了hprof后缀的文件
    3. 确定问题
      1. 需分析heap dump文件,见「工具-MAT」章节
  • 其次:java.lang.OutOfMemoryError: Metaspace
    1. 原因:加载到内存中的class的数量或体积太大导致
    2. 增大aws_startup.sh的-XX:MetaspaceSize=1024m -XX:MaxMetaspaceSize=1024m为2048m即可,一般情况下1024足够,除非安装的应用特别多

  集群节点不可用/集群节点丢失

  此类未造成OOM但服务不可用问题相对宕机来讲,更难定位,因为宕机后有明显线索。
  • 线索来源
    1. 后台切换节点切换不过去
    2. 集群节点反复丢失/加入
    3. 页面提示xx节点不可用
    4. 或者提示:同步出错,请重试
  • 原因
    1. 绝大部分原因是由于GC停顿时间过长导致,解决方式见「问题-服务响应慢-GC时间过长」章节
    2. 极少情况是网络抖动导致
  • 确定问题
    1. 在系统响应慢时,执行命令导出heap dump,分析内存中有哪些对象导致GC慢
    2. 分析heap dump见「工具-MAT」章节

  服务响应慢

    观察SLA >3秒的线程,如果:
  • 单个请求慢,查看堆栈确定问题原因
    1. 等待数据库返回
      1. 优化SQL,添加索引等
      2. 如果是流程表/任务表数据量很大(千万以上)可以考虑分库分表(SAD应用)
    2. 其他如等待网络返回,需要具体情况具体分析
  • 整个平台响应慢
    1. 优先考虑大量对象进入内存导致或其他代码漏洞导致GC时间过长
    2. 实时查看GC时间是否过长,见「工具-jstat」章节
    3. 统计查看GC时间是否过长
      1. 开启jvm的GC参数,会在相应目录下产生gc文件
      2. 用工具分析GC时间,见「工具-gc日志分析」章节

  CPU使用率高

    需要安装监控工具监控CPU使用情况,持续>80%时,就要分析是正常业务还是代码Bug。
  • 正常情况:从SLA观察并发线程数很多,且请求响应时间尚可,可以考虑增加CPU资源。
  • 异常情况1:从SLA观察到的并发线程数并不多,但CPU持续高位运行。
    1. 关注>3秒的线程堆栈
    2. 用jvisualvm对cpu采样分析,见「工具-jvisualvm」章节
  • 异常情况2:频繁GC造成
    1. 可用jstat工具查看GC情况,见「工具-jstat」章节
    2. 此类情况需要分析是正常业务对象还是代码漏洞,前者增大堆内存即可(-Xmx和-Xms),后者需要导出dump分析对象情况,见「工具-MAT」

  无法创建线程

  报错java.lang.OutOfMemoryError: unable to create new native thread
  • 原因:创建线程太多,已超过操作系统能承载的最大数量。
    1. 线程池使用错误导致创建太多线程
    2. 慢请求导致线程持续累积(慢请求原因很多,可从sla >3秒的线程堆栈寻找线索)
    3. 系统压力确实太大,需要增加CPU和内存配置
  • 分析:导出thread dump(命令:jstack -l pid),分析:见「工具-fastthread.io」

工具

  Memory Analyzer (MAT)

  • 关注点1(重点):Leak Suspects部分
    1. 大多数时候,是由于查询大量数据库数据进入内存导致,可能是平台Bug,也可能是二开代码。此部分如何在日常运维中预防,见「运维监控-数据库」章节
  • 关注点2:对象直方图,按照Retained Heap(该类对象hold住的内存大小)排序,可以分析对象是合理的cache还是bug产生的大量对象
  • 关注点3:线程情况,按照Retained Heap(该线程hold住的内存大小)排序,关注前几个hold住大对象的线程
  • MAT能展示的信息非常多,可以以各种角度分析对象情况,甚至可以用OQL语句(类似SQL)过滤查询每个对象的数量

  fastthread.io

  该网站主要用来分析线程情况,会以各种视角展示线程。也可以分析crash日志(见「问题-宕机」部分)
  • 关注点1:总的线程数(1500以上就值得警惕,如果是>2000,基本可以断定有问题)
    1. 线程绝对不是越多越好,尤其注意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/
    1. 重点关注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秒的线程,此处太慢轻则影响用户体验,严重累积则导致系统不可用/宕机。
    1. 点击时间按钮打开堆栈,分析慢的原因。可能是慢sql、请求外部接口、处理大量数据等。
    2. 线程卡住之后,只能重启平台解决,无法kill掉线程。(强行kill可能导致资源泄露或其他不可控问题,java已废弃线程的stop方法)
  • 巡检关注2:Top5线程,系统启动以来最慢的5个线程,可能线程已经运行结束,所以无法查看堆栈,所以只能提供线索。
  • 巡检关注3:SQL返回条数告警(6.4.3以后),默认>1W告警。返回行数太多时,容易造成GC停顿时间过长甚至是OOM错误。同数据库返回条数监控,需要配合使用,区别:
    1. 优点:AWS平台可以记录下调用SQL的位置(有详细堆栈)
    2. 缺点:一次性返回超出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返回条数告警,需要配合使用,区别:
    1. 优点:不受Java服务器宕机影响,理论上可记录所有事故SQL
    2. 缺点:只能记录SQL,无法准确判断AWS的调用代码位置,需要根据经验去排查平台。
  • 巡检关注2:慢SQL。此类SQL会影响用户体验,增大Java服务器并发压力,严重的话会导致大量请求积累,从而导致宕机。(所以需要巡检关注SLA的>3秒的线程)

结束语

  1. 对于系统性问题的思考、理解,以上只是抛砖引玉,需要不断学习实践总结。比如MAT的各种对象信息、zabbix的各种jvm监控指标含义等。
  2. 寻找解决方案时,强烈建议google,效率n倍加(可以用翻译软件)
  1. 平时解决问题时积攒的零散知识,感觉缺乏底层理解时,可以先记录,然后找“系统性”学习的机会。(首推极客时间,其次慕课网
posted on 2022-11-13 15:51  一只阿木木  阅读(1159)  评论(0编辑  收藏  举报