故障快速定位手册
在系统运维过程中,当收到明确的故障告警时,
- 常见故障类型及说明
- 容量类故障:
存储容量包括服务器磁盘空间、NAS盘空间、数据库表空间、数据库数据盘空间等。服务器空间告警主要原因有日志及临时业务文件占用磁盘较多同时清理策略缺失或者策略不合理导致;数据库表空间告警只要是业务表数据量大,同时表中带有大字段都会导致表空间增长过快。尤其要关注跑批及放量期间流水表中的大字段的增长情况。
-
- CPU使用率故障:
当应用及数据库服务器的CPU的使用率超过90%时会收到故障管理流程。应用CPU使用率高的场景有业务高并发导致的CPU使用率高,该场景下一般等业务高峰期结束以后即可恢复。才外还有日志异常输出、程序中不合理的循环、内存溢出等也会导致应用服务器CPU使用率高的。数据库CPU高的场景主要是有跑批中对大批量的数据进行dml操作导致。
-
- 内存溢出:
在应用运行过程中程序往内存里读入大量的数据时,同时内存又没有及时回收就会导致内存溢出。内存溢出最为常见的场景有数据库大表的全表或大量数据查询导致,其次文件读写也会导致部分内存溢出。
-
- 数据库锁表:
数据库并发场景下因事务控制不合理或者数据库操作不合理导致死锁,尤其是对表进行大数据量delete操作时,会导致严重的死锁,或者并发跑批时多个线程对同一资源进行操作时也会导致死锁。
-
- 接口超时故障:
当应用CPU占用过高或者内存溢出时,新进的业务因申请不到服务器的资源,导致线程等待从而引起接口超时;除此之外慢SQL也会导致接口超时;还有就是外部接口响应超时也会导致
- 故障快速定位(各类故障的具体定位方法)
- 容量类故障:
针对具体容量告警事项,服务器容量可登录具体的服务器查看
-
- CPU使用率故障:
可能原因包含业务逻辑问题(死循环)、频繁GC以及线程上下文切换过多。
排查步骤
1、使用top定位到占用cpu过高的进行PID
top
2、通过ps aux | grep PID命令
ps -mp pid -o THREAD,tid,time | sort -rn
3、将需要的线程ID转换为16进制格式
printf "%x\n" tid
4、打印线程的堆栈信息 到了这一步具体看堆栈的日志来定位问题了
jstack pid |grep tid -A 30
5、执行 “jmap -dump:format=b,file=filename 进程ID”,导致某进程下内存heap输出到文件中,可以通过eclipse的mat工具查看内存中有哪些对象比较多。
-
- 内存溢出故障:
- 堆内存不足(java.lang.OutOfMemoryError: Java heap space)
- 内存溢出故障:
原因
1、代码中可能存在大对象分配
2、可能存在内存泄露,导致在多次GC之后,还是无法找到一块足够大的内存容纳当前对象。
解决方法
1、检查是否存在大对象的分配,最有可能的是大数组分配
2、通过jmap命令,把堆内存dump下来,使用mat工具分析一下,检查是否存在内存泄露的问题
3、如果没有找到明显的内存泄露,使用 -Xmx 加大堆内存
4、还有一点容易被忽略,检查是否有大量的自定义的 Finalizable 对象,也有可能是框架内部提供的,考虑其存在的必要性
-
-
- 永久代/元空间溢出
-
报错信息:
java.lang.OutOfMemoryError: PermGen space
java.lang.OutOfMemoryError: Metaspace
原因
永久代是 HotSot 虚拟机对方法区的具体实现,存放了被虚拟机加载的类信息、常量、静态变量、JIT编译后的代码等。
JDK8后,元空间替换了永久代,元空间使用的是本地内存,还有其它细节变化:
字符串常量由永久代转移到堆中
和永久代相关的JVM参数已移除
出现永久代或元空间的溢出的原因可能有如下几种:
1、在Java7之前,频繁的错误使用String.intern方法
2、生成了大量的代理类,导致方法区被撑爆,无法卸载
3、应用长时间运行,没有重启
解决方法
永久代/元空间 溢出的原因比较简单,解决方法有如下几种:
1、检查是否永久代空间或者元空间设置的过小
2、检查代码中是否存在大量的反射操作
3、dump之后通过mat检查是否存在大量由于反射生成的代理类
4、放大招,重启JVM
-
-
- 方法栈溢出
-
报错信息:
java.lang.OutOfMemoryError : unable to create new native Thread
原因
出现这种异常,基本上都是创建的了大量的线程导致的,以前碰到过一次,通过jstack出来一共8000多个线程。
解决方法
1、通过 *-Xss *降低的每个线程栈大小的容量
2、线程总数也受到系统空闲内存和操作系统的限制,检查是否该系统下有此限制:
/proc/sys/kernel/pid_max
/proc/sys/kernel/thread-max
max_user_process(ulimit -u)
/proc/sys/vm/max_map_count
-
- 数据库锁表:
--锁表查询SQL
SELECT object_name, machine, s.sid, s.serial#
FROM gv$locked_object l, dba_objects o, gv$session s
WHERE l.object_id = o.object_id
AND l.session_id = s.sid;
根据脚本查询到对应锁表的事务,定位到业务代码,排查业务逻辑。现场联系dba杀掉锁表进程,保障业务进行。
-
- 接口超时故障:
根据日志分析接口超时的位置,一般超时的原因如下
- SQL执行时间过长
- 调用外部接口时间过长
- 业务处理数据量过大
- 业务循环过多
- 服务器压力导致程序执行缓慢
- 数据库压力导致SQL执行缓慢
解决方法
- 优化执行慢的SQL,分析执行计划,采用优化索引或者绑定索引的方式提高SQL执行效率
- 单节点服务器上大量超时,可以手动下线改节点。服务器恢复正常后再上线
- 减少单接口处理的业务量
- 优化循环业务代码,减少多层循环执行的业务
例:慢SQL排查分析过程:
- 在日志中查找耗时较久的SQL(业务日志中会打印SQL的执行时间)
- 根据SQL文本在em中(性能-SQL-搜索SQL)中搜索对应sql,可以根据SQL文本内容进行模糊搜索;数据源选项中勾选 游标高速缓存 和AWR快照
- 根据搜索结果,或者执行时间确定搜索结果
- 查看SQL详细信息,分析sql当时的执行计划和统计信息。确定sql耗时较久的原因
- 根据执行计划确定sql的优化方案,采用优化索引或者绑定索引的方式提高SQL执行效率
- 常见的故障排查方式:
- 登录服务器查看(数据库、服务器)
- EM查看数据库状态
- 日志排查
- 生产业务
- 数据库锁表查询
- 生产DUMP包定位
针对原因不明确的故障,通过checkList逐一排查
- 查看服务器运行状态:内存、CPU、存储
- 应用进程查看:EURCA,服务器进程
- 查看数据库EM状态:等待进程、慢sql
- 锁表和会话查询:重点排查TX锁(数据库健康巡检手册)
- 异常日志排查:日终中的ERROR及EXCEPTION日志
- 生产dump包导出:(dump故障分析手册)