说之前
由于业务应用 bug(本身或引入第三方库)、环境原因、硬件问题等原因,线上服务出现故障 / 问题几乎不可避免。例如,常见的现象包括请求超时、用户明显感受到系统发生卡顿等等。
作为一个合格的研发人员(技术人员),不仅要能写得一手好代码,掌握如何排查问题技巧也是研发人进阶必须掌握的实战技能。这里提到的排查问题不仅仅是在Coding的过程中Debug,还包括测试阶段、线上发布阶段问题的排查。特别是在生产环境中,一般是没办法或很难进行Debug操作的。而通过掌握服务线上问题排查思路并能够熟练排查问题常用工具 / 命令 / 平台来获取运行时的具体情况,这些运行时信息包括但不限于运行日志、异常堆栈、堆使用情况、GC情况、JVM参数情况、线程情况等。
排查出问题并找到根本原因加以解决,其实是一件很成就感的事情。曾经有人问过我:“你是怎么想到问题出现在xxx的?又是怎么确认根本原因是xxx的?”,我只能轻描淡写的回答:“靠经验”,其实这里说的“靠经验”是很模糊的,一直以来大家可能都觉得排查问题要靠经验,但是又说不出具体通过什么样的经验排查出了问题。而本质上排查定位线上问题是具有一定技巧或者说是经验规律的,排查者如果对业务系统了解得越深入,那么相对来说定位也会容易一些。排查问题的关键是什么?一句话总结:给一个系统定位排查问题的时候,知识、经验是关键,数据是依据,工具是运用知识处理数据的手段!在此,我将结合自身经历、总结,说关于“问题排查”的方法论,希望能与您产生更多的共鸣。
注:由于针对不同技术问题,所用到的排查工具,命令千差万别,所以本文将只介绍思路,不涉及具体排查命令的介绍。
有哪些常见问题
那我们经常说遇到这样那样的问题,那到底有哪些问题,问题又集中在哪些方面?对于不同技术框架、语言族所可能引发的问题也会存在很大的差异,但基本的套路排查思路都还是一致的,以Java为例。
所有 Java 服务的线上问题从系统表象来看归结起来总共有四方面:CPU、内存、磁盘、网络。例如 CPU 使用率峰值突然飚高、内存溢出 (泄露)、磁盘满了、网络流量异常、FullGC 等等问题。
基于这些现象我们可以将线上问题分成两大类: 系统异常、业务服务异常。
1、系统异常
常见的系统异常现象包括: CPU 占用率过高、CPU 上下文切换频率次数较高、磁盘满了、磁盘 I/O 过于频繁、网络流量异常 (连接数过多)、系统可用内存长期处于较低值 (导致 oom killer) 等等。
这些问题如果是在Linux系统下可以通过 top(cpu)、free(内存)、df(磁盘)、dstat(网络流量)、pstack、vmstat、strace(底层系统调用) 等工具获取系统异常现象数据。
注:
CPU 是系统重要的监控指标,能够分析系统的整体运行状况。对CPU的分析或监控指标,一般包括运行队列、CPU 使用率和上下文切换等,内存是排查线上问题的重要参考依据,内存问题很多时候是引起 CPU 使用率较高的主要因素。
而经常遇到内存占用飙高它的原因可能有很多。最常见的就是内存泄露。可以得到堆dump文件后,进行对象分析。如果有大量对象在持续被引用,并没有被释放掉,那就产生了内存泄露,就要结合代码,把不用的对象释放掉。
2、业务服务异常
常见的业务服务异常现象包括: PV 量过高、服务调用耗时异常、线程死锁、多线程并发问题、频繁进行 Full GC、异常安全攻击扫描等。
频繁的 GC 将导致应用吞吐量下降、响应时间增加,甚至导致服务不可用。
问题排查方法论
一、排查问题犹如破案
排查线上问题犹如警察破案一样,是一个不停分析线索,推理的过程,但在准备排查问题之前,我们应该明白三个认知:
系统出现异常是正常的
时至今日计算机系统已经变得异常复杂,一次用户请求可能要经过发送请求,DNS解析,运营商网络,负载均衡,服务器,虚拟机(容器),视业务逻辑的复杂程度可能还要调用组件,缓存,存储和数据库等。每个环节都可能出现问题,有的组件又是分布式的,大大增加的排查问题的难度,所以出现问题后不要慌,保持好的心态。
首要任务是恢复系统
飞机在发生紧急情况下,飞行员的首要任务是保持飞机飞行,相比保证乘客与飞机安全着陆,故障定位和排除是次要目标”,所以恢复线上系统是首要任务,而不是立马找到它发生的原因。
真相永远只有一个
计算机是一门科学,而且计算机的世界里都是由0或1组成,在这个世界里只有是或否,没有中间地带,所以在计算机世界凡事都有根本原因,没有偶然发生,一切都是必然。正如墨菲定律所提到的“如果事情有变坏的可能,不管这种可能性有多小,它总会发生!”