一、环境准备

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、实战拓谱图

二、操作和分析

1、发现问题

首先在第一个终端执行的命令来运行Nnginx和PHP应用

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

第二个终端测试确认Nnginx已经正常启动

[root@nfs ~]# curl http://192.168.118.97:10000
It works!

第二个终端测试Nnginx服务的性能

# 并发 10 个请求测试 Nginx 性能,总共测试 100 个请求
[root@nfs ~]# ab -c 10 -n 100 http://192.168.118.97:10000/
......
Requests per second: 24.07 [#/sec] (mean)
......

第二个终端测试Nnginx服务的性能加大压力测试

# 并发 10000个请求测试 Nginx 性能,总共测试 100 个请求
[root@nfs ~]# ab -c 10 -n 10000 http://192.168.118.97:10000/
......
Requests per second: 24.07 [#/sec] (mean)
......

top查看终端一

这里看一看到,系统中有几个php-fpm进程的CPU使用率加起来接近200%;而每个CPU的用户使用率已经超过了
98%,接近跑和,这样就可以确认,正是用户空间的PHP-fpm进程导致CPU使用率骤升

终端一运行perf 命令

按方向键切换到PHP-FPM,再按下回车键展开php-fpm的调用关系,你会发现,调用关系最终到了sqrt 和 add_function。看来,我们需要从这两个函数入手了

2、解决问题

我们拷贝出 Nginx 应用的源码,看看是不是调用了这两个函:

# 从容器 phpfpm 中将 PHP 源码拷贝出来
$ docker cp phpfpm:/app . # 使用 grep 查找函数调用
$ grep sqrt -r app/ # 找到了 sqrt 调用
app/index.php: $x += sqrt($x);
$ grep add_function -r app/ # 没找到 add_function 调用,这其实是 PHP 内置函数

原来只有 sqrt 函数在 app/index.php 文件中调用了。那最后一步,我们就该看看这个文件的源码了:

cat app/index.php
<?php
// test only.
$x = 0.0001;
for ($i = 0; $i <= 1000000; $i++) {
$x += sqrt($x);
} echo "It works!"

测试代码没删除就直接发布应用了,为了方便你验证优化后的效果。我们修复好的应用打包成了一个

Docker 镜像,你可以在第一个终端中执行下面的命令来运行它

# 停止原来的应用
$ docker rm -f nginx phpfpm
# 运行优化后的应用
$ docker run --name nginx -p 10000:80 -itd feisky/nginx:cpu-fix
$ docker run --name phpfpm -itd --network container:nginx feisky/php-fpm:cpu-fix

终端二验证修复的效果

[root@nfs ~]#  ab -c 10 -n 10000 http://192.168.118.97:10000/
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/ Benchmarking 192.168.118.97 (be patient)
Completed 1000 requests
Completed 2000 requests
Completed 3000 requests
Completed 4000 requests
Completed 5000 requests
Completed 6000 requests
Completed 7000 requests
Completed 8000 requests
Completed 9000 requests
Completed 10000 requests
Finished 10000 requests Server Software: nginx/1.15.6
Server Hostname: 192.168.118.97
Server Port: 10000 Document Path: /
Document Length: 153 bytes Concurrency Level: 10
Time taken for tests: 10.776 seconds
Complete requests: 10000
Failed requests: 992
(Connect: 0, Receive: 0, Length: 992, Exceptions: 0)
Write errors: 0
Non-2xx responses: 9008
Total transferred: 2900048 bytes
HTML transferred: 1387152 bytes
Requests per second: 928.00 [#/sec] (mean)
Time per request: 10.776 [ms] (mean)
Time per request: 1.078 [ms] (mean, across all concurrent requests)
Transfer rate: 262.82 [Kbytes/sec] received

从这里你可以发现,现在美秒的平均请求数,已经从原来的24变成了928

三、执行perf top -g -p (php-fpm进程号),发现不了sqrt函数

1、故障现象

我的系统是centos7,上次实战用 perf top -g -p pid没有看到函数名称,只能看到一堆十六进制的东西,然后老师给了解决方法,我转述下:
分析:当没有看到函数名称,只看到了十六进制符号,下面有Failed to open /usr/lib/x86_64-linux-gnu/libxml2.so.2.9.4, continuing without symbols 这说明perf无法找到待分析进程所依赖的库。这里只显示了一个,但其实依赖的库还有很多。这个问题其实是在分析Docker容器应用时经常会碰到的一个问题,因为容器应用所依赖的库都在镜像里面。

2、解决办法

老师给了两个解决思路:
(1)在容器外面构建相同路径的依赖库。这种方法不推荐,一是因为找出这些依赖比较麻烦,更重要的是构建这些路径会污染虚拟机的环境。
(2)在容器外面把分析纪录保存下来,到容器里面再去查看结果,这样库和符号的路径就都是对的了。

操作:
(1)在Centos系统上运行 perf record -g -p <pid>,执行一会儿(比如15秒)按ctrl+c停止
(2)把生成的 perf.data(这个文件生成在执行命令的当前目录下,当然也可以通过查找它的路径 find | grep perf.data或 find / -name perf.data)文件拷贝到容器里面分析:

docker cp perf.data phpfpm:/tmp
docker exec -i -t phpfpm bash
$ cd /tmp/
$ apt-get update && apt-get install -y linux-perf linux-tools procps
$ perf_4.9 report

注意:最后运行的工具名字是容器内部安装的版本 perf_4.9,而不是 perf 命令,这是因为 perf 会去跟内核的版本进行匹配,但镜像里面安装的perf版本有可能跟虚拟机的内核版本不一致。
注意:上面的问题只是在centos系统中有问题,ubuntu上没有这个问题

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

  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. [转帖]springboot+k8s+抛弃springcloud.eureka

    springboot+k8s+抛弃springcloud.eureka https://www.cnblogs.com/lori/p/12048743.html springboot开发微服务框架一般 ...

  2. 删除链表中的倒数第N个节点

    题目 给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点. 示例: 给定一个链表: ->->->->, 和 n = . 当删除了倒数第二个节点后,链表变为 -&g ...

  3. 创建Maven项目时,GroupId和Artifact Id该怎么填写呢?

    1.什么是groupid和artifactId? groupid和artifactId被统称为“坐标”是为了保证项目唯一性而提出的,如果你要把你项目弄到maven本地仓库去,你想要找到你的项目就必须根 ...

  4. Linux查看进程启动时间和已持续时间

    ps -eo pid,lstart,etime,cmd | grep zzlogic  

  5. APUE—UNIX文件系统

    在linux系统中——一切都是文件. 1. 磁盘物理结构 磁盘的物理结构如下: 磁盘由很多盘面组成,而盘面上则是由很多同心圆环组成的磁道,每个磁道又被切割成许多扇区.所有磁盘面的同一个磁道构成一个柱面 ...

  6. 未能加载文件或程序集“Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35”或它的某一个依赖项。系统找不到指定的文件。

    网站部署到IIS提示Microsoft.Web.Infrastructure,未能加载 解决方案 使用nuget安装 Microsoft.Web.Infrastructure拷贝到bin目录下面

  7. 初学者学习golang可能遇到的坑

    我也是个golang初学者,刚入门的话,有些"坑"还是不好发现的.如map只是定义了然后就拿来使用,变量的值覆盖等. 本来打算写一篇的,后面发现有人写的挺不错的,我就把里面的有些坑 ...

  8. vue中通过hls.js播放m3u8格式的视频

    近期做了一个功能,是接入一个海康的摄像头的监控视频,怎么获取m3u8的视频这里就不在叙述了,只说一下怎么将m3u8格式的视频成功播放 一.m3u8和HLS介绍 1.M3U8文件是指UTF-8编码格式的 ...

  9. Java 之 JDK 1.8 新增日期时间类型

    一.原来的日期时间 Java1.0中包含了一个Date类,但是它的大多数方法已经在Java 1.1引入Calendar类之后被弃用了.而Calendar并不比Date好多少.它们面临的问题是: ① 可 ...

  10. MySQL Execution Plan--合理利用隐式的业务逻辑

    问题描述 优化过程中遇到一个SQL: SELECT SUM(user_value) FROM user_log ; 其执行计划为: . row *************************** ...