性能分析小案例系列,可以通过下面链接查看哦

https://www.cnblogs.com/poloyy/category/1814570.html

系统架构背景

  • VM1:用作 Web 服务器,来模拟性能问题
  • VM2:用作 Web 服务器的客户端,来给 Web 服务增加压力请求
  • 使用两台虚拟机(均是 Ubuntu 18.04)是为了相互隔离,避免交叉感染

VM2 运行 ab 命令,初步观察 Nginx 性能

简单介绍 ab 命令

  • ab(apache bench)是一个常用的 HTTP 服务性能测试工具
  • 可以向目标服务器并发发送请求

运行 ab 命令

并发 100 个请求测试 VM1 的 Nginx 性能,总共测试 1000 个请求

ab -c  -n  http://172.20.72.58:10000/

从 ab 的输出结果可以看到,Nginx 能承受的每秒平均请求数只有 145.68(有点差强人意)

那到底是哪里出了问题呢

接下来,我们将通过一系列的命令来观察哪里出问题了

通过命令分析 VM1 的性能问题

VM2 长时间运行 ab 命令

并发 5 个请求,持续并发请求 10min

ab -c  -t  http://172.20.72.58:10000/

接下来的命令都在 VM1 上执行

top 查看系统 CPU 使用率、进程 CPU 使用率、平均负载

top

结果分析

  • 平均负载已远超 CPU数量(2)
  • Nginx、docker、php 相关的进程总的 CPU 使用率大概 40%左右
  • 但是系统 CPU 使用率(us+sy)已达到 96%了,空闲 CPU(id)只剩下 3.7%

提出疑问

为什么进程所占用的 CPU 使用率并不高,但是系统 CPU 使用率和平均负载会这么高?

回答疑问,分析进程列表

  • containerd-shim:运行容器的,3.3% 的 CPU 使用率挺正常
  • Nginx 和 php-fpm:运行 Web 服务的,占用的 CPU 使用率也才 5-6%
  • 再往后就没有什么占用 CPU 使用率的进程了

嘶,发现 top 并没有满足我们的需求,看来得祭出另一个命令了

pidstat 查看是否有异常进程的 CPU 使用率过高

每秒取一次结果,共取 10 次

pidstat  

结果分析

跟 top 命令的结果差不多,Nginx、dockerd、php-fpm 的 CPU 使用率偏高,但是加起来并没有用户态 CPU 使用率这么高

问题来了

用户 CPU 使用率已经达到 55%,但却找不到时哪个进程有问题,这到底是咋肥事?难道是命令太辣鸡了吗?

答案

命令的存在肯定是有它的意义,问题肯定是出在我们自己身上,是否遗漏了什么关键信息?

再次运行 top 命令

结果分析

发现了一个关键点,就绪队列有 6 个进程处于 R 状态

6 个正常吗?

  • 回想一下 ab 测试的参数,并发请求数是 5
  • 再看进程列表里, php-fpm 的数量也是 6, 再加上 Nginx
  • 好像同时有 6 个进程也并不奇怪

仔细瞧一瞧

php-fpm、Nginx、docker 这么多个进程只有 1 个 php-fpm 进程是 R 状态的,其他都处于 S(Sleep)状态,这就奇怪了

找到真正处于 R 状态的进程

调整 top 列表排序规则

在 top 列表中,按 shift + f,进入 top 列表的显示规则页面

可以看到默认排序的列是 %CPU,这里改成 S 列,就可以更快看到哪些进程的状态是 R

来看看到底有哪些 R 状态的进程呢

  • 真正处于 Running(R)状态的,却是几个 stress 进程
  • 这几个 stress 进程就比较奇怪了,需要做进一步的分析

观察一段时间, stress 进程的变化

每次刷新列表,stress 进程的数量都会变化,而且 PID(进程号)也会跟着变

更具体的动态查看 stress 进程的变化

watch -d 'ps aux | grep stress | grep -v grep'

  • 其实可以看到 stress 进程有三种状态:R、S、Z
  • 多个 stress 进程在不断生成,由 R 变 S 再变 Z
  • 三种变化:进程PID、进程数量、进程状态

进程 PID 在不断变化的可能原因

原因一:进程在不停地崩溃重启

比如因为段错误、配置错误等等,这时,进程在退出后可能又被监控系统自动重启

原因二:这些进程都是短时进程

  • 就是在其他应用内部通过 exec 调用的外面命令
  • 这些命令一般都只运行很短的时间就会结束,很难用 top 这种间隔时间比较长的工具发现

stress 进程 PID 为什么在不断变化

首先,我并没有手动执行 stress 命令,所以它很大可能是通过其他命令去执行的

找到 stress 的父进程

pstress | grep stress

stress 是被 php-fpm 调用的子进程,并且进程数量不止一个(这里是 2 个)

grep 查找是否有代码在调用 stress

grep stress -r app/

可以看到, index.php 文件是包含了 stress 命令

index.php 源码

<?php
// fake I/O with stress (via write()/unlink()).
$result = exec("/usr/bin/stress -t 1 -d 1 2>&1", $output, $status);
if (isset($_GET["verbose"]) && $_GET["verbose"]==1 && $status != 0) {
echo "Server internal error: ";
print_r($output);
} else {
echo "It works!";
} ?>r
  • 很明显,就是 index.php 中调用了 stress 命令
  • 每个请求都会调用一个 stress 命令,模拟 I/O 压力
  • stress 会通过 write()  、 unlink() 对 I/O 进程进行压测

猜测

就是因为 stress 模拟 I/O 压力导致的 CPU 使用率升高

灵魂拷问

如果是模拟 I/O 压力,为什么 pidstat 命令的时候 iowait% 并不高呢

看来得继续深挖分析

VM2 带参数发送请求

index.php 有一句源码值得注意

if (isset($_GET["verbose"]) && $_GET["verbose"]==1 && $status != 0) 

当请求传了 verbose 参数时...

VM2 带 verbose 参数发送请求

curl http://172.20.72.58:10000?verbose=1

  • 看到错误消息 mkstemp failed: Permission denied ,以及 failed run completed in 0s
  • 原来 stress 命令并没有成功,它因为权限问题失败退出了

结果分析猜测

正是由于权限错误,大量的 stress 进程在启动时初始化失败,过多的进程上下文切换,进而导致 CPU 使用率的升高

关于进程上下文切换的猜测验证

未压测前的系统上下文切换次数

只有 200 左右

压测后的系统上下文切换次数

直蹦 10000 左右了,上下文切换次数的确涨了很多

stress 进程的上下文切换次数

前面是猜测 stress 进程有问题,那就来看看 stress 进程的上下文切换次数

pidstat -w  | grep stress

  • 黄圈:自愿上下文切换次数和非自愿上下文切换次数并不高
  • 蓝圈:进程PID 一直在变化

灵魂拷问

为什么 stress 进程的上下文切换次数这么低?

回答

  • 因为 stress 是短时进程
  • 会频繁的产生新的 stress 进程
  • 系统需要从旧的 stress 进程切换到新的 stress 进程再运行,这样切换次数就会增加

VM1 通过 perf 查看性能分析报告

上一篇文章中也见到过这个 perf 命令

记录性能事件

等待大约 15 秒后按 Ctrl+C 退出

perf record -g

查看性能报告,结果分析

perf report

  • 占了 CPU 时钟事件的前几名都是 stress 进程
  • 而且调用栈中比例最高的是随机数生成函数 random() ,看来它的确就是 CPU 使用率升高的元凶了

拓展-swapper 进程是啥?

从上面报告其实可以看到排在前面的还有 swapper 进程,那么它是啥呢?

  • swapper 跟 SWAP 没有任何关系
  • 它只在系统初始化时创建 init 进程,之后,它就成了一个最低优先级的空闲任务
  • 也就是说,当 CPU 上没有其他任务运行时,就会执行 swapper
  • 所以,你可以称它 为“空闲任务”

  • 当没有其他任务时,可以看到 swapper 基本占满了 CPU 时钟事件
  • 它的主要耗费都是 do_idle,也就是在执行空闲任务

优化问题

只要修复权限问题,并减少或删除 stress 的调用

总结

  • CPU 使用率升高的主要原因就是短时进程 stress 频繁的进行进程上下文切换
  • 对于短时进程,我们需要通过 pstree 命令找到它的父进程,然后再分析父进程存在什么问题

注意

当然,实际生产环境中的问题一般都要比这个案例复杂,在你找到触发瓶颈的命令行后,却可能发现,这个外部命令的调用过程是应用核心逻辑的一部分,并不能轻易减少或者删除;这时,你就得继续排查,为什么被调用的命令,会导致 CPU 使用率升高或 I/O 升高等问 题

分析整体思路

  1. 短时间压测,发现服务器性能低下
  2. 长时间压测,让服务器保持一个高负载的状态,从而可以慢慢分析问题所在
  3. 通过 top 命令监控系统资源情况,发现用户态的 CPU 使用率(us)较高,且空闲 CPU (id) 很低
  4. 但是找不到用户态 的 CPU 使用率很高的进程,最高就 6%
  5. 进一步通过 pidstat 查看是否有 CPU 使用率异常高的进程
  6. 发现 pidstat 行不通,再次通过 top 命令仔细观察
  7. 发现 Running(R)状态的进程有 6 个之多,但是 CPU 使用率较高的进程并没有处于 R 状态
  8. 切换 top 列表的排序规则,倒序,集中看 R 状态的进程一段时间,发现是 stress 进程,而且时多时少,进程 PID 还会变化
  9. 通过 watch 实时观察 stress 进程,发现 stress 进程会从从 R 状态变到 S 再变到 Z,而且会不断生成新的 stress 进程
  10. 猜测 stress 进程可能是短时进程,通过其他进程进行调用它
  11. 通过 pstree 找到 stress 进程的父进程,发现是 php-fpm 进程,接下来就是分析父进程了
  12. 通过 grep 查找 stress 命令是否存在 Nginx 应用中,发现存在 index.php 文件中
  13. 查看源码,确认每次请求都会触发 stress 命令
  14. stress 命令可以模拟 I/O 压力的,通过 top 看到 iowait 其实并不算高
  15. 在 VM2 发送带请求参数,可以确认 stress 命令是执行失败的
  16. 可以猜测大量的请求进来,导致大量的 stress 进程初始化执行失败,从而增加进程上下文切换次数增加,最终导致 CPU 使用率升高
  17. 通过 vmstat 对比压测前后的上下文切换次数,可以发现压测的上下文切换次数的确增加了
  18. 通过 pidstat 查看 stress 的上下文切换次数,但发现并不高,其实是因为 stress 是短时进程,上下文切换次数主要增加在旧进程切换到新进程的运行上
  19. 通过 perf record 录制性能事件 30s
  20. 通过 perf report 查看性能报告,可以看到占用 CPU 时钟事件的前几名都是 stress 进程,然后调度比例最高的是 random 函数
  21. 确认问题根源就是 stress 进程调用了 random 函数

炒鸡重点

  • 其实有时候 top、vmstat、pidstat 命令用完了可能还不一定能发现问题根源
  • 这个时候就要更加细心的查看这些命令返回结果其中的猫腻,虽然可能找不到问题根源,但可能会发现某些线索
  • perf 虽然强大,但并不是一开始分析就适合用它的

性能分析(3)- 短时进程导致用户 CPU 使用率过高案例的更多相关文章

  1. 性能分析(2)- 应用程序 CPU 使用率过高案例

    性能分析小案例系列,可以通过下面链接查看哦 https://www.cnblogs.com/poloyy/category/1814570.html 系统架构背景 其中一台用作 Web 服务器,来模拟 ...

  2. 性能分析(4)- iowait 使用率过高案例

    性能分析小案例系列,可以通过下面链接查看哦 https://www.cnblogs.com/poloyy/category/1814570.html 前言 前面两个案例讲的都是上下文切换导致的 CPU ...

  3. 06 案例篇:系统的 CPU 使用率很高,但为啥却找不到高 CPU 的应用?

    上一节我讲了 CPU 使用率是什么,并通过一个案例教你使用 top.vmstat.pidstat 等工具,排查高 CPU 使用率的进程,然后再使用 perf top 工具,定位应用内部函数的问题.不过 ...

  4. 4 系统的 CPU 使用率很高,但为啥却找不到高 CPU的应用?

    上一节讲了 CPU 使用率是什么,并通过一个案例教你使用 top.vmstat.pidstat 等工具,排查高 CPU 使用率的进程,然后再使用 perf top 工具,定位应用内部函数的问题.不过就 ...

  5. 性能分析(5)- 软中断导致 CPU 使用率过高的案例

    性能分析小案例系列,可以通过下面链接查看哦 https://www.cnblogs.com/poloyy/category/1814570.html 前言 软中断基本原理,可参考这篇博客:https: ...

  6. 查询执行成本高(查询访问表数据行数多)而导致实例 CPU 使用率高是 MySQL 非常常见的问题

    MySQL CPU 使用率高的原因和解决方法_产品性能_常见问题_云数据库 RDS 版-阿里云 https://help.aliyun.com/knowledge_detail/51587.html ...

  7. CPU使用率过高分析方法

    项目过程中发现,应用服务器经常会出现CPU使用率较高的情况,需要定位出具体代码问题. 1.用top命令,根据CPU使用率排序,找出消耗cpu最高的进程 2.找出该进程下消耗CPU最高的线程(命令:to ...

  8. 空循环导致CPU使用率很高

    业务背景 业务背景就是需要将多张业务表中的数据增量同步到一张大宽表中,后台系统基于这张大宽表开展业务,所以就开发了一个数据同步工具,由中间件采集binlog消息到kafka里,然后我去消费,实现增量同 ...

  9. 性能测试分析过程(二)cpu 使用率过高的分析方法

    Linux 系统下 cpu 使用率过高的分析方法 1.通过 top 命令可以很明显查看出哪个进程耗cpu比较高 2. ps -mp 25147-o THREAD,tid,time\top -Hp pi ...

随机推荐

  1. HBase写入异常RejectedExecutionException

    HBase在大数据量并发写入时,写一段时间后HBase监控界面出现告警,写入程序日志里频繁出现异常java.util.concurrent.RejectedExecutionException: 从异 ...

  2. 无题 II 二分图最大匹配

    题目描述 这是一个简单的游戏,在一个n*n的矩阵中,找n个数使得这n个数都在不同的行和列里并且要求这n个数中的最大值和最小值的差值最小. Input 输入一个整数T表示T组数据. 对于每组数据第一行输 ...

  3. HDFS概述及其优缺点

    HDFS产生背景 随着数据量越来越大,在一个操作系统存不下所有的数据,那么就分配到更多的操作系统管理的磁盘中,但是不方便管理和维护,迫切需要一种系统来管理多台机器上的文件,这就是分布式文件管理系统.H ...

  4. SpringBoot系列之前后端接口安全技术JWT

    @ 目录 1. 什么是JWT? 2. JWT令牌结构怎么样? 2.1 标头(Header) 2.2 有效载荷(Playload) 2.3 签名(Signature) 3. JWT原理简单介绍 4. J ...

  5. python虚拟环境 + 批量pip + 换源

    python虚拟环境 + 批量pip + 换源 虚拟环境 曾经我是一个小白,不管运行什么项目都用一个环境,后来项目多了,有的是Django1.11的有的是Django2的,有的项目只能在3.6上运行, ...

  6. Scala 面向对象(一):类与对象基础(一)

    1 如何定义类 [修饰符] class 类名 { 类体 } 定义类的注意事项 1)scala语法中,类并不声明为public,所有这些类都具有公有可见性(即默认就是public), 2)一个Scala ...

  7. 《Head First 设计模式》:装饰者模式

    正文 一.定义 装饰者模式动态地将责任(功能)附加到对象上.若要扩展功能,装饰者提供了比继承更有弹性的替代方案. 要点: 装饰者和被装饰者有相同的超类型. 可以用一个或多个装饰者包装一个对象. 既然装 ...

  8. 关于JS深拷贝和浅拷贝

    最近在前端开发中遇到一些问题,就是数组中的某个对象或某个对象的值改变之后,在不刷新页面的时候需要重新渲染值时,页面显示的还是原来的数据.比如: data{ A:[{id:1,num:1},{id:2, ...

  9. Python Ethical Hacking - Malware Packaging(4)

    Converting Python Programs to Linux Executables Note: You can not execute the program on Linux by do ...

  10. 使用Java带你打造一款简单的外卖系统

    [一.项目背景] 随着互联网时代的快速发展,便捷人民的生活,提高生活质量,外卖系统应运而生. 人们也喜欢享受着"足不出户,美食到家"的待遇,促使网上订餐行业快速发展. [二.项目目 ...