機器配置:2 CPU,8GB 內存 預先安裝 docker、sysstat、perf等工具php
[root@luoahong ~]# docker -v Docker version 18.09.1, build 4c52b90 [root@luoahong ~]# rpm -qa|grep sysstat sysstat-12.1.2-1.x86_64
機器配置:1 CPU,2GB 內存 預先安裝ab 等工具linux
[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/
首先在第一個終端執行的命令來運行Nnginx和PHP應用nginx
$ docker run --name nginx -p 10000:80 -itd feisky/nginx $ docker run --name phpfpm -itd --network container:nginx feisky/php-fpm
第二個終端測試確認Nnginx已經正常啓動docker
[root@nfs ~]# curl http://192.168.118.97:10000 It works!
第二個終端測試Nnginx服務的性能apache
# 併發 10 個請求測試 Nginx 性能,總共測試 100 個請求 [root@nfs ~]# ab -c 10 -n 100 http://192.168.118.97:10000/ ...... Requests per second: 24.07 [#/sec] (mean) ......
第二個終端測試Nnginx服務的性能加大壓力測試ubuntu
# 併發 10000個請求測試 Nginx 性能,總共測試 100 個請求 [root@nfs ~]# ab -c 10 -n 10000 http://192.168.118.97:10000/ ...... Requests per second: 24.07 [#/sec] (mean) ......
top查看終端一centos
這裏看一看到,系統中有幾個php-fpm進程的CPU使用率加起來接近200%;而每一個CPU的用戶使用率已經超過了
98%,接近跑和,這樣就能夠確認,正是用戶空間的PHP-fpm進程致使CPU使用率驟升bash
終端一運行perf 命令併發
按方向鍵切換到PHP-FPM,再按下回車鍵展開php-fpm的調用關係,你會發現,調用關係最終到了sqrt 和 add_function。看來,咱們須要從這兩個函數入手了app
咱們拷貝出 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
個人系統是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容器應用時常常會碰到的一個問題,由於容器應用所依賴的庫都在鏡像裏面。
老師給了兩個解決思路:
(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上沒有這個問題