Linux性能優化實戰學習筆記:第六講


一、環境准備

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資源

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM