排错套路
排错环境
开发环境:IDE单步调试
测试环境:使用编程语言自带的调试工具(Java的jvisualvm/Arthas,Golang的
net/http/pprof
或runtime/pprof
)生产环境:存在权限管控,不允许调试工具从远程附加进程,且生产环境以恢复为主,没有足够的时间和现场来排查。
生产环境排错
生产问题的排查很大程度依赖监控,因为,生产环境出现问题时,要尽快恢复应用,就不可能保留完整现场用于排查和测试。因此,是否有充足的信息(日志、监控和快照)可以了解过去、还原现场就成了关键。
日志
确保错误、异常信息可以被完整地记录到文件日志中。
确保生产上程序的日志级别是 INFO 以上。
记录日志要使用合理的日志优先级:
DEBUG 用于开发调试、
INFO 用于重要流程信息、
WARN 用于需要关注的问题、
ERROR 用于阻断流程的错误。
监控
做好充足的,多层次的监控(监控层数取决于应用的部署方案,有一层 OS 就要做一层监控):
主机层次:对 CPU、内存、磁盘、网络等资源做监控。
网络层次:监控专线带宽、交换机基本情况、网络延迟。
中间件和存储层次:不仅仅是监控进程对 CPU、内存、磁盘 IO、网络使用的基本指标,更重要的是监控组件内部的一些重要指标。(比如Prometheus的exporter来对接各种中间件和存储系统)
应用层次:需要监控 JVM 进程的类加载、内存、GC、线程等常见指标(比如Micrometer来做应用监控),此外还要确保能够收集、保存应用日志、GC 日志。
快照
应用进程在某一时刻的快照。
比如生产环境的 Java 应用设置 -XX:+HeapDumpOnOutOfMemoryError
和 -XX:HeapDumpPath=…
这 2 个 JVM 参数,用于在出现 OOM 时保留堆快照。
分析定位套路
定位问题,首先要定位问题出在哪个层次上。比如是应用程序自身的问题还是外部因素导致的问题,如果是资源消耗型问题,可能没有异常,需要监控指标配合显性问题来定位。
程序自身问题
比如新版本的BUG,首先应该回滚,尽快恢复生产环境,然后再分析对比版本之间的差异。
外部因素
比如主机、中间件、数据库的问题,按照不同层次分为主机问题以及中间件和存储问题。
主机层次的问题使用工具排查:
CPU 相关问题,可以使用 top、vmstat、pidstat、ps 等工具排查;
内存相关问题,可以使用 free、top、ps、vmstat、cachestat、sar 等工具排查;
IO 相关问题,可以使用 lsof、iostat、pidstat、sar、iotop、df、du 等工具排查;
网络相关问题,可以使用 ifconfig、ip、nslookup、dig、ping、tcpdump、iptables 等工具排查。
中间件和存储层次的问题:
排查组件所在主机是否有问题;
排查组件进程基本情况,观察各种监控指标;
查看组件的日志输出,特别是错误日志;
进入组件控制台,使用一些命令查看其运作情况。
资源消耗型问题(先通过重启和扩容解决,保留一个节点作为现场):
CPU使用过高:
top -Hp pid
,输入大写的 P 将线程按照 CPU 使用率排序,再使用编程语言自带的工具查看对应的线程,定位出问题的线程当时的调用栈。内存泄漏或OOM:查看具体堆内存使用情况,可使用编程语言自带的工具。
网络问题:一般是外部因素,可以抓包分析。
IO问题:一般是代码引起资源未释放。
分析定位时的注意点
考虑先有鸡还是先有蛋的问题
分类寻找规律
根据调用拓扑分析
考虑资源限制
考虑资源相互影响
网络问题要区分:客户端、服务端、传输
快照类工具和趋势类工具结合使用
不要轻易怀疑监控
如果因为监控缺失等原因无法定位到根因的话,相同问题就有再出现的风险
最后更新于
这有帮助吗?