阿里面试题:线上接口变慢,如何排查

商务办公
这是面试阿里时的一道题,也是平时工作中处理线上问题经常遇到的一类问题,所以耐心看完吧,无论是工作还是面试,帮助都很大。

[[383726]]

文转载自微信公众号「菜鸟飞呀飞」,作者刘进坤 。转载本文请联系菜鸟飞呀飞公众号。

前言

这是面试阿里时的一道题,也是平时工作中处理线上问题经常遇到的一类问题,所以耐心看完吧,无论是工作还是面试,帮助都很大。

首先线上接口变慢,原因可能有很多,有可能是网络,有可能是慢 SQL,有可能是服务本身出现了问题,还有可能是机器达到了性能瓶颈。而机器性能瓶颈也又可以分为磁盘 IO 瓶颈、CPU 性能瓶颈、网卡瓶颈等等,本文主要从 CPU 出现性能瓶颈这个角度来分析下问题出现在哪儿。

为什么选 CPU 来分析呢?这是因为这通常是我们排查问题的第一步,自下而上排查,而通过 CPU 往往能帮助我们分析出问题出现在哪儿。

top

首先使用 top 命令,可以看到机器有多少个 CPU,以及 CPU 过去 1 分钟、5 分钟、15 分钟的平均负载,各个 CPU 的使用率等信息。今天主要分析下 CPU 的负载和使用率的区别,这两个指标经常容易搞混。

CPU 的负载(load)和使用率(utilization)

首先,需要明确的是,CPU 的负载(load)和使用率这两个指标并不是一码事。第一,它们的计算公式不一样,也就是说它们所代表的含义也就不一样;第二,这两个指标如果异常,我们排查问题的方向也就不同。

负载的计算公式

load = (D+R)/SUM(ALL)

D 和 R 是什么意思呢?

一台 linux 机器在运行时会有很有很多进程,这些进程按照状态可以细分为 7 类:

  1. D(TASK_UNINTERRUPTIBLE)状态:不可中断的睡眠状态,处于睡眠状态,但是不可以被中断。一般由 IO 等待引起(磁盘 IO,网络 IO、外设 IO 等),出现非常短暂,一般很难用 ps 或者 top 等工具捕捉到,sleep 状态下的进程不会占用 CPU 资源。
  2. R(TASK_RUNNING)状态:可执行状态,这种进程处于 CPU 的可执行队列中,正在运行或者等待 CPU 运行。
  3. S(TASK_INTERRUPTIBLE)状态:可中断的睡眠状态,不同于 D,该状态下的进程也是休眠状态,但是可以被中断。这种进程一般在等待某种事件的发生,例如:socket 连接、信号量等。一但这些时间啊完成,进程就会被唤醒,如果不是在高负载时期,大部分进程都处于 S 状态,不占用 CPU 资源。
  4. T(TASK_STOPPED)状态:暂停状态,进程处于停止运行状态。
  5. t(TASK_TRACED)状态:跟踪状态。
  6. Z(EXIT_ZOMBIE)状态:僵死态,这种进程实际上已经结束运行了,只不过父进程还没有回收它的资源(比如进程的描述符、PID 等),僵死进程会释放掉除了进程入口之外的所有资源。
  7. X(EXIT_DEAD)状态:死亡态

「因此 D+R 表示的是机器的整体负载,即 CPU 负载(正在运行着的进程)+Disk 负载+网络负载+其他外设负载,当出现负载高时,那么问题可能不仅仅出现在 R 态的进程,还有可能是磁盘和网络 IO 引起的。」

CPU 的使用率

CPU 是分时间片运行的,每个时间片会分配给一个进程(或者线程)。

CPU 的使用率 = CPU 执行非系统空闲进程的时间 / CPU 总的执行时间

CPU 总的执行时间又可以细分为四大类:

1.用户进程使用时间(User Time)

  • i. us(user time):用户态进程占用的 CPU 时间
  • ii. ni(nice time):改变过优先级的用户态进程占用的 CPU 时间

2.系统内核使用时间(System Time)

  • a) sys(System time):系统内核进程占用的 CPU 时间
  • b) si(softirq time):软中断占用的 CPU 时间
  • c) hi(hard irq time):硬中断占用的 CPU 时间

3.被抢占的时间(Steal Time)

  • a) st(steal time) 发生抢占,被强制中断发生的等待时间

4.空闲时间(Idle Time)

  • a) id(idle time):除磁盘 IO 等待时间以外其它等待时间
  • b) wa(waiting time):等待磁盘 IO 的时间

因此,当 CPU 的使用率较高的时候,问题可能出现在用户进程,也可能出现在系统内核,究竟是谁导致的,可以通过机器表现出来的现象或者其他的命令工具去排查(看下文)。

负载高使用率低

这种情况是通常是由于 D 状态(不可中断的睡眠状态)的进程数过多导致的,即 CPU 使用率不高,但是 IO 负载很高。因此需要进一步定位是磁盘 IO 导致的,还是网络 IO 导致的。

如何查看磁盘 IO 相关的信息呢?

可以使用命令 「iostat -x 2 5」 去查看,还可以使用 iotop 和 pidstat 查看进程的 IO 情况。

负载高且使用率高

负载高且使用率高这种情况产生的原因比较多,大概可以分为下面三大类.

1.sys 高。这个时候需要进一步查看上下文的切换(可以通过 vmstat 命令)

i. 如果是非自愿上下文切换,这种情况可能是由于 cpu 资源抢占比较激烈,由于时间片已到的原因,被系统强制调度,进而发生上下文的切换。

ii. 如果是自愿上下文切换,这种情况可能存在大量 IO 操作或者内存等系统资源存在瓶颈,大量进程无法获取到系统资源,导致上下文切换。可以使用 iostat 查看 IO 情况后者 free 查看内存情况

2.si 高,需要进一步查看软中断的类型。中断相关的信息存储在/proc/softirqs (软中断)、/proc/interrupts(硬中断),可以通过 cat 命令查看。si 高通常可能是网络 IO 或者线程调度引起的,其中软中断又可以分为两大类:

a). NET_TX 和 NET_RX NET_TX 指的是发送网络包的软中断,NET_RX 指的是接收网络包的软中断。如果这两者较高,那么就是系统的网络 IO 存在瓶颈的可能性较大

b). SCHED 进程调度或者负载均衡引起的中断,这种中断出现较多时,通常伴随进程的上下文切换,一般与非自愿上下文切换一同出现,可能存在 CPU 瓶颈

3..us 高,这表示用户进程占用 CPU 较高。可能出现的问题是:

代码出现死循环,此时表现为多核 CPU 均出现 us 较高。(top 和 jstack 定位具体线程的堆栈)

程序属于 CPU 密集计算型,此时表现为多核 CPU 出现 us 较高

内存问题,出现 Full GC,通常只有单核 CPU 的 us 较高(jstat -util pid)

资源等待造成线程池满,引发 CPU 使用率飙高,通常伴随线程池异常出现(查看应用日志)

如果是代码死循环问题,这种问题比较简单,通常的定位手段为:先使用 top 查询出占用 CPU 使用率最高的进程 ID(pid),然后使用 「top -H -p pid」 命令查询出 pid 这个进程中占用 CPU 资源最高的线程 id,此时查询出来的线程 id 为十进制,还需要将十进制的线程 id 转换为 16 进制,可以使用如下命令:「printf "0x%x" 线程 id」,接着使用「jstack pid 线程 id」 查看该线程的堆栈信息了,根据堆栈信息就可以快速定位代码中哪儿出现了死循环。

如果是 GC 问题,可以使用「jstat -util pid 1000」 命令,每隔 1 秒中打印一下 JVM 中新老年代各个区域的使用情况,系统多久发生一次 Full GC,每次 GC 花费的时间。

 

责任编辑:武晓燕 来源: 菜鸟飞呀飞
相关推荐

2024-04-07 00:00:00

垃圾收集器内存

2018-12-03 09:42:32

Java程序员阿里面试

2015-07-13 09:45:32

阿里校招

2021-08-05 05:04:50

热部署模型字节

2018-01-02 09:23:38

数据分析算法阿里巴巴

2020-06-04 14:40:40

面试题Vue前端

2024-03-12 09:34:01

2021-11-02 10:10:38

面试元素语言

2023-11-13 07:37:36

JS面试题线程

2011-03-24 13:27:37

SQL

2021-01-20 07:16:07

幂等性接口token

2022-02-21 08:41:50

Redis

2021-05-31 10:08:44

工具脚本主机

2014-09-19 11:17:48

面试题

2015-09-02 09:32:56

java线程面试

2012-06-28 14:35:49

Web

2009-06-06 18:36:02

java面试题

2009-06-06 18:34:05

java面试题

2024-03-04 00:00:00

系统架构核心

2024-03-11 10:52:34

点赞
收藏

51CTO技术栈公众号