一、环境准备

1、安装软件包

终端1

机器配置:2 CPU,8GB 内存 预先安装 docker、sysstat、perf等工具

[root@luoahong ~]# docker -v
Docker version 18.09.1, build 4c52b90
[root@luoahong ~]# rpm -qa|grep sysstat
sysstat-12.1.2-1.x86_64

终端2

机器配置:1 CPU,2GB 内存 预先安装ab 等工具

[root@nfs ~]#yum -y install httpd-tools
[root@nfs ~]# ab -V
This is ApacheBench, Version 2.3 <$Revision: 1430300 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

2、实战拓谱图

3、环境模拟

终端一

docker run --name nginx -p 10000:80 -itd feisky/nginx:sp
$ docker run --name phpfpm -itd --network container:nginx feisky/php-fpm:sp

终端二

测试nginx是否启动

# 192.168.118.97 是第一台虚拟机的 IP 地址
$ curl http://192.168.118.97:10000/
It works!

性能测试

# 并发 100 个请求测试 Nginx 性能,总共测试 1000 个请求
$ ab -c 100 -n 1000 http://192.168.118.97:10000/
This is ApacheBench, Version 2.3 <$Revision: 1706008 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd,
...
Requests per second: 87.86 [#/sec] (mean)
Time per request: 1138.229 [ms] (mean)
...

继续压力测试

ab -c 5 -t 600 http://192.168.118.97:10000/

二、定位问题(top、pidstat、ps)

1、top定位

2、pidstat定位

[root@luoahong ~]# pidstat 1
Linux 3.10.0-957.5.1.el7.x86_64 (luoahong) 05/04/2019 _x86_64_ (2 CPU) 03:41:55 PM UID PID %usr %system %guest %wait %CPU CPU Command
03:41:56 PM 0 3 0.00 2.94 0.00 0.00 2.94 0 ksoftirqd/0
03:41:56 PM 0 9 0.00 6.86 0.00 27.45 6.86 0 rcu_sched
03:41:56 PM 0 14 0.00 15.69 0.00 9.80 15.69 1 ksoftirqd/1
03:41:56 PM 0 7500 4.90 2.94 0.00 0.98 7.84 0 vmtoolsd
03:41:56 PM 0 9451 0.00 1.96 0.00 0.00 1.96 1 dockerd
03:41:56 PM 27 9928 0.00 0.98 0.00 0.00 0.98 0 mysqld
03:41:56 PM 0 10133 0.98 0.00 0.00 0.00 0.98 1 containerd-shim
03:41:56 PM 0 10804 0.00 0.98 0.00 4.90 0.98 1 kworker/1:0
03:41:56 PM 0 10835 0.98 3.92 0.00 0.00 4.90 1 containerd-shim
03:41:56 PM 101 10891 0.00 5.88 0.00 15.69 5.88 0 nginx
03:41:56 PM 1 84378 0.98 2.94 0.00 3.92 3.92 0 php-fpm
03:41:56 PM 1 84388 0.00 1.96 0.00 3.92 1.96 1 php-fpm
03:41:56 PM 1 84395 0.98 0.98 0.00 4.90 1.96 1 php-fpm
03:41:56 PM 1 84411 0.00 0.98 0.00 3.92 0.98 0 php-fpm
03:41:56 PM 1 84413 0.00 1.96 0.00 8.82 1.96 1 php-fpm
03:41:56 PM 0 102735 0.00 0.98 0.00 0.00 0.98 1 pidstat

3、top再次定位

你有没有发现,nginx和所有的PHP-FPM都处于sleep状态,二真正处于Running(R)状态的,却是几个 stress 进程,这几个stree比较奇怪,需要我们做进一步的分析

4、pidstat再次定位

[root@luoahong perf-tools]# pidstat -p 24226
Linux 3.10.0-957.5.1.el7.x86_64 (luoahong) 05/04/2019 _x86_64_ (2 CPU) 03:47:45 PM UID PID %usr %system %guest %wait %CPU CPU Command

奇怪、居然没有任何输出。难道是pidstat命令出问题了吗?在怀疑西能工具出问题前,最好还是先用其他工具交叉确认一下

5、ps定位

[root@luoahong perf-tools]# ps aux|grep 24226
root 66566 0.0 0.0 112708 980 pts/0 S+ 15:46 0:00 grep --color=auto 24226

还是没有输出,现在终于发现问题,原来这个进程已经不存在了,所以pidstat就没有任何输出,既然进程都没了

那西能问题应该跟着没了吧。我们在top命令确认一下;

top
...
%Cpu(s): 80.9 us, 14.9 sy, 0.0 ni, 2.8 id, 0.0 wa, 0.0 hi, 1.3 si, 0.0 st
... PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
6882 root 20 0 12108 8360 3884 S 2.7 0.1 0:45.63 docker-containe
6947 systemd+ 20 0 33104 3764 2340 R 2.7 0.0 0:47.79 nginx
3865 daemon 20 0 336696 15056 7376 S 2.0 0.2 0:00.15 php-fpm
6779 daemon 20 0 8184 1112 556 R 0.3 0.0 0:00.01 stress
...

可是,刚刚看到的stree进程不存在了,怎么还在运行呢?原来这次stree进程的pid跟前面不一样了,原来的pid不见了现在的是6779

进程的 PID 在变,这说明什么呢?在我看来要么是这些进程在不停地重启,要么就是全新的进程,这无非也就两个原因

第一原因:进程在不停地崩溃重启,比如因为段错误、配置错误等等这时,进程在退出后可能又被监控系统自动重启了。
第二原因:这些进程都是短时进程,也就是在其他应用内部通过 exec 调用的外面命令。这些命令一般都只运行很短的时间就会结束,你很难用 top 这种间隔时间比较长的工具发现(上面的案例,我们碰巧发现了)

6、用pstree | grep [xx],这样定位到具体的调用方法里。

[root@luoahong ~]# pstree | grep stress
| | | |-2*[php-fpm---sh---stress---stress]
| | | |-php-fpm---sh---stress

三、定位到具体的代码

1、用grep [xx] -r [项目文件]

查找是不是代码在调用stree命令

# 拷贝源码到本地
$ docker cp phpfpm:/app . # grep 查找看看是不是有代码在调用 stress 命令
$ grep stress -r app
app/index.php:// fake I/O with stress (via write()/unlink()).
app/index.php:$result = exec("/usr/local/bin/stress -t 1 -d 1 2>&1", $output, $status);

2、找到具体代码位置

找到了,果然是app/index.php

cat app/index.php
<?php
// fake I/O with stress (via write()/unlink()).
$result = exec("/usr/local/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!";
}
?>

3、给请求加入 verbose=1 参数后,就可以查看 stress的输出

[root@nfs ~]# curl http://192.168.118.97:10000/?verbose=1
Server internal error: Array
(
[0] => stress: info: [103660] dispatching hogs: 0 cpu, 0 io, 0 vm, 1 hdd
[1] => stress: FAIL: [103661] (563) mkstemp failed: Permission denied
[2] => stress: FAIL: [103660] (394) <-- worker 103661 returned error 1
[3] => stress: WARN: [103660] (396) now reaping child worker processes
[4] => stress: FAIL: [103660] (400) kill error: No such process
[5] => stress: FAIL: [103660] (451) failed run completed in 0s
)

从这里我们可以猜测,正式由于权限错误,大量的stress进程在启动是初始化失败,进而导致用户CPU使用率的升高

4、perf验证定位是否准确

1、perf record -g 记录

perf record -g
docker cp perf.data phpfpm:/tmp
docker exec -i -t phpfpm bash

2、 用perf report查看是否可以定位到问题

cd /tmp/
apt-get update && apt-get install -y linux-perf linux-tools procps
perf_4.9 report

四、execsnoop和实验过程中遇到的问题

1、execsnoop查看短时进程详细信息

execsnoop 就是一个专为短时进程设计的工具它通过 ftrace 实时监控进程的 exec() 行为,并输出短时进程的基本信息,
包括进程 PID、父进程 PID、命令行参数以及执行的结果。

用 execsnoop 监控上述案例,就可以直接得到 strress 进程的父进程 PID 以及它的命令行参数,并可以发现大量的 stress 进程在不停启动:

git clone --depth 1 https://github.com/brendangregg/perf-tools
cd perf-tools/
[root@luoahong perf-tools]# ./bin/execsnoop
Tracing exec()s. Ctrl-C to end.
Instrumenting sys_execve
PID PPID ARGS
70342 70322 gawk -v o=1 -v opt_name=0 -v name= -v opt_duration=0 [...]
70344 50765 <...>-70344 [001] d... 2372.510629: execsnoop_sys_execve: (SyS_execve+0x0/0x30)
70343 70341 cat -v trace_pipe
70340 0 /usr/local/bin/stress -t 1 -d 1
70346 70339 /usr/local/bin/stress -t 1 -d 1
70347 70344 /usr/local/bin/stress -t 1 -d 1
70351 50796 <...>-70351 [000] d... 2372.553884: execsnoop_sys_execve: (SyS_execve+0x0/0x30)
70352 50775 <...>-70352 [000] d... 2372.555010: execsnoop_sys_execve: (SyS_execve+0x0/0x30)
70353 70351 /usr/local/bin/stress -t 1 -d 1
70355 50776 <...>-70355 [000] d... 2372.557869: execsnoop_sys_execve: (SyS_execve+0x0/0x30)
70357 70355 /usr/local/bin/stress -t 1 -d 1
70356 70352 /usr/local/bin/stress -t 1 -d 1

execsnoop所用的ftrace是一种常用的动态追踪技术,一般用于分析linux内核的运行时为

2、pstree的安装

yum install psmisc

3、小结

如果碰到不好解释的CPU问题时,比如现象:

通过top观察CPU使用率很高,但是看下面的进程的CPU使用率好像很正常,通过pidstat命令查看cpu也很正常。但通过top查看task数量不正常,处于R状态的进程是可疑点。

首先要想到可能是短时间的应用导致的问题,如下面的两个:
(1)应用里直接调用了其他二进制程序,这些程序通常运行时间比较短,通过top等工具发现不了
(2)应用本身在不停地崩溃重启,而启动过程的资源初始化,很可能会占用很多CPU资源

Linux性能优化实战学习笔记:第六讲的更多相关文章

  1. Linux性能优化实战学习笔记:第四十一讲

    一.上节回顾 上一节,我们探究了网络延迟增大问题的分析方法,并通过一个案例,掌握了如何用hping3.tcpdump.Wireshark.strace 等工具,来排查和定位问题的根源. 简单回顾一下, ...

  2. Linux性能优化实战学习笔记:第九讲

    一.中断的魅力 1.中断在生活的魅力 比如你订了一份外卖,但是不确定外卖什么时候送到,也没有别的方法了解外卖的进度,但是,配送员送外卖是不等人的,到了你这儿没人取的话,就直接走人了.所以你指能苦苦等着 ...

  3. Linux性能优化实战学习笔记:第三十六讲

    一.上节总结回顾 上一节,我们回顾了经典的 C10K 和 C1000K 问题.简单回顾一下,C10K 是指如何单机同时处理 1 万个请求(并发连接 1 万)的问题,而 C1000K 则是单机支持处理 ...

  4. Linux性能优化实战学习笔记:第五十六讲

    一.上节回顾 上一节,我带你一起梳理了,性能问题分析的一般步骤.先带你简单回顾一下. 我们可以从系统资源瓶颈和应用程序瓶颈,这两个角度来分析性能问题的根源. 从系统资源瓶颈的角度来说,USE 法是最为 ...

  5. Linux性能优化实战学习笔记:第四十三讲

    一.上节回顾 上一节,我们了解了 NAT(网络地址转换)的原理,学会了如何排查 NAT 带来的性能问题,最后还总结了 NAT 性能优化的基本思路.我先带你简单回顾一下. NAT 基于 Linux 内核 ...

  6. Linux性能优化实战学习笔记:第四十五讲

    一.上节回顾 专栏更新至今,四大基础模块的最后一个模块——网络篇,我们就已经学完了.很开心你还没有掉队,仍然在积极学习思考和实践操作,热情地留言和互动.还有不少同学分享了在实际生产环境中,碰到各种性能 ...

  7. Linux性能优化实战学习笔记:第五十二讲

    一.上节回顾 上一节,我们一起学习了怎么使用动态追踪来观察应用程序和内核的行为.先简单来回顾一下.所谓动态追踪,就是在系统或者应用程序还在正常运行的时候,通过内核中提供的探针,来动态追踪它们的行为,从 ...

  8. Linux性能优化实战学习笔记:第五十五讲

    一.上节回顾 上一节,我们一起学习了,应用程序监控的基本思路,先简单回顾一下.应用程序的监控,可以分为指标监控和日志监控两大块. 指标监控,主要是对一定时间段内的性能指标进行测量,然后再通过时间序列的 ...

  9. Linux性能优化实战学习笔记:第五十八讲

    一.上节回顾 专栏更新至今,咱们专栏最后一部分——综合案例模块也要告一段落了.很高兴看到你没有掉队,仍然在积极学习思考.实践操作,并热情地分享你在实际环境中,遇到过的各种性能问题的分析思路以及优化方法 ...

  10. Linux性能优化实战学习笔记:第三十一讲

    一.上节回顾 上一节,我们一起回顾了常见的文件系统和磁盘 I/O 性能指标,梳理了核心的 I/O 性能观测工具,最后还总结了快速分析 I/O 性能问题的思路. 虽然 I/O 的性能指标很多,相应的性能 ...

随机推荐

  1. 【前端知识体系-JS相关】深入理解MVVM和VUE

    1. v-bind和v-model的区别? v-bind用来绑定数据和属性以及表达式,缩写为':' v-model使用在表单中,实现双向数据绑定的,在表单元素外使用不起作用 2. Vue 中三要素的是 ...

  2. python asyncio asyncio wait

    import asyncio import time async def get_html(url): print("start get url") await asyncio.s ...

  3. 汇总Anaconda与ROS冲突解决方法

    汇总一下在网上找到的Anaconda与ROS冲突解决方法,如果还有其他人找到其他方法,欢迎留言. anaconda和ros的安装就不介绍了. 1. 在某视频网站上一个印度小哥提出的方法 安装完成后,在 ...

  4. Kubernetes 安全概念详解

    Kubernetes 安全框架 API 认证三关 • 访问K8S集群的资源需要过三关:认证.鉴权.准入控制• 普通用户若要安全访问集群API Server,往往需要证书.Token  或者用户名+密码 ...

  5. 【题解】Ples [COCI2011]

    [题解]Ples [COCI2011] 依旧是没有传送门,只有提供了数据的官网. [题目描述] \(N\) 个汉子和 \(N\) 个妹纸一起参加舞会,跳舞时只能是一个汉子一个妹纸配对,现在给出每个人的 ...

  6. Weblogic-SSRF漏洞复现

    Weblogic-SSRF漏洞复现 一.SSRF概念 服务端请求伪造(Server-Side Request Forgery),是一种有攻击者构造形成有服务端发起请求的一个安全漏洞.一般情况下,SSR ...

  7. asp.net mvc4 bundle添加带min的js问题

    今天在用ScriptBundle的时候发现js文件有min的,无法bundle进去,具体我也不知道怎么回事. @Tony Tan 回复:bundles.IgnoreList可以设置 去除min.js的 ...

  8. Entity Framework 导航属性(2)

    1.学校 [Table("School")] public partial class School { public School() { Students = new List ...

  9. 腾讯云-ASP.NET Core+Mysql+Jexus+CDN上云实践

    腾讯云-ASP.NET Core+Mysql+Jexus+CDN上云实践.md 开通腾讯云服务器和Mysql 知识点: ASP.NET Core和 Entity Framework Core的使用 L ...

  10. phpmyadmin 在服务起上检测到错误,请查看窗口底部

    使用phpmyadmin一直提示这个警告,看着难受: 解决: 修改文件:/etc/phpmyadmin/config.inc.php 在最后添加这一句, $cfg['SendErrorReports' ...