1.Unix域Socket通訊
Unix域Socket由於不走網絡,的確能夠提升Nginx和php-fpm通訊的性能,但在高併發時會不穩定。
Nginx會頻繁報錯:
connect() to unix:/dev/shm/php-fcgi.sock failed (11: Resource temporarily unavailable) while connecting to upstream
能夠經過下面兩種方式提升穩定性:
1)調高nginx和php-fpm中的backlog
配置方法爲:在nginx配置文件中這個域名的server下,在listen 80後面添加default backlog=1024。
同時配置php-fpm.conf中的listen.backlog爲1024,默認爲128。
2)增長sock文件和php-fpm實例數
再新建一個sock文件,在Nginx中經過upstream模塊將請求負載均衡到兩個sock文件背後的兩套php-fpm實例上。
2.php-fpm參數調優
2.1進程數
php-fpm初始/空閒/最大worker進程數
pm.max_children = 300
pm.start_servers = 20
pm.min_spare_servers = 5
pm.max_spare_servers = 35
2.2最大處理請求數
最大處理請求數是指一個php-fpm的worker進程在處理多少個請求後就終止掉,master進程會從新respawn一個新的。
這個配置的主要目的是避免php解釋器或程序引用的第三方庫形成的內存泄露。
pm.max_requests = 10240
2.3最長執行時間
最大執行時間在php.ini和php-fpm.conf裏均可以配置,配置項分別爲max_execution_time和request_terminate_timeout。
3.php-fpm的高CPU使用率排查方法
3.1CPU使用率監控方法
1)top命令
直接執行top命令後,輸入1就能夠看到各個核心的CPU使用率。並且經過top -d 0.1能夠縮短採樣時間。
下面的sar貌似最短只能是1秒。
2)sar命令
sar和iostat命令的安裝:
sysstat.x86_64 : The sar and iostat system monitoring commands
yum install -y sysstat.x86_64
執行sar -P ALL 1 100。-P ALL表示監控全部核心,1表示每1秒採集,100表示採集100次。
輸出結果以下:
CPU %user %nice %system %iowait %steal %idle
all 85.54 0.00 5.69 0.00 0.00 8.76
0 74.75 0.00 25.25 0.00 0.00 0.00
1 98.00 0.00 2.00 0.00 0.00 0.00
2 89.22 0.00 3.92 0.00 0.00 6.86
3 91.00 0.00 2.00 0.00 0.00 7.00
4 75.00 0.00 9.00 0.00 0.00 16.00
5 94.95 0.00 5.05 0.00 0.00 0.00
6 95.00 0.00 4.00 0.00 0.00 1.00
7 87.88 0.00 4.04 0.00 0.00 8.08
8 93.94 0.00 3.03 0.00 0.00 3.03
9 88.00 0.00 3.00 0.00 0.00 9.00
10 89.11 0.00 2.97 0.00 0.00 7.92
11 82.35 0.00 3.92 0.00 0.00 13.73
12 73.27 0.00 7.92 0.00 0.00 18.81
13 81.44 0.00 4.12 0.00 0.00 14.43
14 77.23 0.00 6.93 0.00 0.00 15.84
15 78.79 0.00 4.04 0.00 0.00 17.17
3.2開啓慢日誌
配置輸出php-fpm慢日誌,閥值爲2秒:
request_slowlog_timeout = 2
slowlog = log/$pool.log.slow
利用sort/uniq命令分析彙總php-fpm慢日誌:
[root@b28-12 log]# grep -v "^$" www.log.slow.tmp | cut -d " " -f 3,2 | sort | uniq -c | sort -k1,1nr | head -n 50
5181 run() /www/test.net/framework/web/filters/CFilter.php:41
5156 filter() /www/test.net/framework/web/filters/CFilterChain.php:131
2670 = /www/test.net/index.php
2636 run() /www/test.net/application/controllers/survey/index.php:665
2630 action() /www/test.net/application/controllers/survey/index.php:18
2625 run() /www/test.net/framework/web/actions/CAction.php:75
2605 runWithParams() /www/test.net/framework/web/CController.php:309
2604 runAction() /www/test.net/framework/web/filters/CFilterChain.php:134
2538 run() /www/test.net/framework/web/CController.php:292
2484 runActionWithFilters() /www/test.net/framework/web/CController.php:266
2251 run() /www/test.net/framework/web/CWebApplication.php:276
1799 translate() /www/test.net/application/libraries/Limesurvey_lang.php:118
1786 load_tables() /www/test.net/application/third_party/php-gettext/gettext.php:254
1447 runController() /www/test.net/framework/web/CWebApplication.php:135
參數解釋:
sort: 對單詞進行排序
uniq -c: 顯示惟一的行,並在每行行首加上本行在文件中出現的次數
sort -k1,1nr: 按照第一個字段,數值排序,且爲逆序
head -10: 取前10行數據
3.3用strace跟蹤進程
1)利用nohup將strace轉爲後臺執行,直到attach上的php-fpm進程死掉爲止:
nohup strace -T -p 13167 > 13167-strace.log &
參數說明:
-c 統計每一系統調用的所執行的時間,次數和出錯的次數等.
-d 輸出strace關於標準錯誤的調試信息.
-f 跟蹤由fork調用所產生的子進程.
-o filename,則全部進程的跟蹤結果輸出到相應的filename
-F 嘗試跟蹤vfork調用.在-f時,vfork不被跟蹤.
-h 輸出簡要的幫助信息.
-i 輸出系統調用的入口指針.
-q 禁止輸出關於脫離的消息.
-r 打印出相對時間關於,,每個系統調用.
-t 在輸出中的每一行前加上時間信息.
-tt 在輸出中的每一行前加上時間信息,微秒級.
-ttt 微秒級輸出,以秒了表示時間.
-T 顯示每一調用所耗的時間.
-v 輸出全部的系統調用.一些調用關於環境變量,狀態,輸入輸出等調用因爲使用頻繁,默認不輸出.
-V 輸出strace的版本信息.
-x 以十六進制形式輸出非標準字符串
-xx 全部字符串以十六進制形式輸出.
-a column
設置返回值的輸出位置.默認爲40.
-e execve 只記錄 execve 這類系統調用
-p 主進程號
2)也能夠用利用-c參數讓strace幫助彙總,很是方便很是強大!
[root@b28-12 log]# strace -cp 9907
Process 9907 attached - interrupt to quit
Process 9907 detached
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
56.61 0.016612 5 3121 read
11.11 0.003259 1 2517 715 stat
8.04 0.002358 7 349 brk
6.02 0.001767 1 1315 poll
4.28 0.001255 6 228 recvfrom
2.71 0.000796 1 671 open
2.54 0.000745 0 2453 fcntl
2.37 0.000696 1 1141 write
1.69 0.000497 1 593 13 access
1.37 0.000403 0 1816 lseek
0.89 0.000262 1 451 22 sendto
0.56 0.000163 1 276 208 lstat
0.49 0.000145 0 384 getcwd
0.31 0.000090 0 1222 fstat
0.28 0.000082 0 173 munmap
0.26 0.000077 0 174 mmap
0.24 0.000069 2 41 socket
0.23 0.000068 0 725 close
0.00 0.000000 0 13 rt_sigaction
0.00 0.000000 0 13 rt_sigprocmask
0.00 0.000000 0 1 rt_sigreturn
0.00 0.000000 0 78 setitimer
0.00 0.000000 0 26 26 connect
0.00 0.000000 0 15 2 accept
0.00 0.000000 0 39 recvmsg
0.00 0.000000 0 26 shutdown
0.00 0.000000 0 13 bind
0.00 0.000000 0 13 getsockname
0.00 0.000000 0 65 setsockopt
0.00 0.000000 0 13 getsockopt
0.00 0.000000 0 8 getdents
0.00 0.000000 0 26 chdir
0.00 0.000000 0 1 futex
------ ----------- ----------- --------- --------- ----------------
100.00 0.029344 18000 986 total
ps:可使用strace學習php解釋器的解釋執行過程
3.4加速PHP解釋執行
若是本身的程序的確沒有問題,只是執行了太多操做,無法再作優化了。則考慮使用APC或xcache等PHP加速器來減小CPU解釋php文件的耗時。
這些PHP加速器在php文件第一次解釋時會生成中間代碼opcode,因此以後的執行會快不少,而且減小了一些CPU的運算。下面以xcache爲例,
看下如何安裝和配置。
安裝xcache命令以下,./configure的參數好多不知道是作什麼用的,官網上也沒說明,因此只開啓--enable-xcache了:
tar zxvf xcache-3.0.3.tar.gz
/usr/local/php/bin/phpize
./configure --with-php-config=/usr/local/php/bin/php-config --enable-xcache
make
make install
php.ini中配置以下,最重要的是標紅的兩個參數,通常推薦xcache.size根據php文件多少來定,xcache.count與CPU核心數相同:
[xcache.admin]
xcache.admin.enable_auth = Off
xcache.admin.user = "xcache"
xcache.admin.pass = ""
[xcache]
xcache.shm_scheme ="mmap"
xcache.size=1024M
xcache.count =16
xcache.slots =8K
xcache.ttl=0
xcache.gc_interval =0
xcache.var_size=16M
xcache.var_count =1
xcache.var_slots =8K
xcache.var_ttl=0
xcache.var_maxttl=0
xcache.var_gc_interval =300
xcache.test =Off
xcache.readonly_protection = Off
;xcache.readonly_protection = On
xcache.mmap_path ="/dev/zero"
;xcache.mmap_path ="/tmp/xcache"
xcache.coredump_directory =""
xcache.cacher =On
xcache.stat=On
xcache.optimizer =Off
[xcache.coverager]
;;xcache.coverager =On
;;xcache.coveragedump_directory =""
常見問題是啓動php-fpm時會報錯:
Cannot open or create file set by xcache.mmap_path, check the path permission or check xcache.size/var_size against system limitation
這是由於/tmp/xcache是一個文件,而不能建立成目錄。
重啓php-fpm服務後,用top命令觀察會發現每一個worker進程的VIRT(包含了swap區)都是xcache.size大小,但REQ變得很小了。
使用上面的配置在使CPU使用率的峯值時間變短了,但峯值時仍是全部核心都會達到90%以上,不知道是否是哪裏沒有配置對。
另外高併發時,/dev/zero這種配置方式常常會致使Nginx 502錯誤。/tmp/xcache和開啓readonly_protection則很穩定。
4.php程序性能監控
經常使用的方法就是開啓xdebug的性能監控功能,將xdebug輸出結果經過WinCacheGrind軟件分析。
php.ini中配置的這幾項是輸出性能信息的:
xdebug.auto_trace = on
xdebug.auto_profile = on
xdebug.collect_params = on
xdebug.collect_return = on
xdebug.profiler_enable = on
xdebug.trace_output_dir = "/tmp"
xdebug.profiler_output_dir ="/tmp"
這樣XDebug會輸出全部執行php函數的性能數據,但產生的文件也會比較大。能夠關閉一些選項如collect_params、collect_return,
來減小輸出的數據量。或者關閉自動輸出,經過在想要監控的函數首尾調用xdebug函數來監控指定的函數。
輸出的文件名相似cachegrind.out.1277560600和trace.3495983249.txt,能夠拿到Windows平臺下用WinCacheGrind進行圖形化分析。
WinCacheGrind使用方法網上有不少介紹,這裏就不詳細說明了。
結束語
以上都是近期作php程序優化工做總結出的一些優化方法,還請經驗豐富的大牛們提出更好的建議,共同交流、進步~
參考資料
1)php-fpm優化方法彙總
2)多Sock文件和php-fpm實例配置