誰貪佔了我的系統資源 php-fpm

from: http://www.perfgeeks.com/?p=599


測試人員向我們反映:在Facebook平臺的遊戲比其它平臺的遊戲明顯更慢。我詢問,是不是因爲翻牆網絡原因。他們說:不是,其它遊戲也比較流暢。使用httpwatch查看了http請求,發現api.php請求花了6秒,且大部分時間是紅色(httpwatch紅色表示服務器運算時間)。平常2秒,現在6秒,服務器處理時間在不同的服務器相差這麼多。直覺告訴:服務器資源。

服務器概況

  • 操作系統:CentOS5.3-64-2.6.18-164.el5
  • 應用服務Nginx0.6、PHP-Fpm、MySQL5.1、PHP5.2、Memcached
  • Memcached僅cached遊戲系統設置與模板參數據

故障檢測

1.別的先不管,先top看一下cpu、ram、swap哪個比較緊張。

由上圖分析,可以看出共有602個進程,其中有601個進程休眠了。這好像有點不對勁,內核進程也就80個左右,加上memcached, nginx, mysqld,也不會超出90個。除了這些,剩下的只有php-fpm管理的php-cgi,難道是…?
CPU顯示,CPU壓力並不大,可以說沒有壓力。我們再看內存使用概要,發現4G的內存,消耗得所剩餘無幾(free+buffers), 95%以上的內存都已分配。交互空間使用情況,我們暫時不去關心。指令top還列出了佔用資源最多的進程,運行時間最久(Time+)的mysqld(約2小時)佔用資源並不是最多。另外,再看php-cgi,單個php-cgi佔用的內存也不算多。所以,可以大膽地猜想:服務器內存資源比較緊張,並沒有被某個進程佔用大量內存,有可能被某些掛起的進程佔着內存沒有釋放。通過free進一步監控內存使用情況,驗證我們的想法。
2.指令free,瞭解RAM資源使用情況。當然,你也可以查看文件/proc/meminfo

我們先來看Mem統計信息,total表示物理內存總量,約4G。used,表示已分配內存,分配了並不表示使用了,包括(buffer&cached)。free指未分配的內存,buffers與cached表示分配了但還沒有被使用的內存。第二行(buffers/cache)的,used表示真正被使用了內存,由第一行的(used-buffer-cached)得到,free則表示還沒有被使用的內存,由第一行的(free+buffer+cached)得到。Swap行則表示內存交換使用情況,少量的(不頻繁地)swpd,是不會影響服務器性能的,因爲系統需要將V類型的內存頁面交換出去或者調整了buffer與cached的大小。但是頻繁地swpd,則有可能意味着服務器物理內存不足,小於指定的swap額定值,需要換出內存頁。

查看free結果的時候,我們主要查看第二行。一眼就能看出4G的內存,其中有3898M內存被用了,還有49M內存沒有,都快用完了。這也證實了我們第一步的猜想,內存被用完。這裏,我們進一步猜想,內存空間嚴重不足的情況下,進程會被blocked,系統會不斷地將不用的數據換出so,將要用的數據讀入si。我們能通過vmstat進一步驗證,我們的這個猜想。

3.指令vmstat監控內存使用情況

作爲對內存監控,我們比較關心swpd、free、si、so。一般系統不繁忙的狀態下,我們看到swpd,so的值不會持續很高,經常爲0。這裏,我們看到swpd值爲1.5G,以及free值很小,再一次表明物理內存不足。其中si報告了每秒從swap區移入到物理內存的內存總量,so報告了每秒從物理內存移出到swap區的內存總量。當然,si有時較大,並不要過份的焦慮,經常碰到一個程序需要較大內存來讀寫媒體文件時,si值就會變大。反倒是so,它通常是一個內存緊缺的一個信號,如果長時間這個值一直保持較大的話,則很有可能內存不夠,小額波動,可以不用理會。接下來,可以通過ps找出消耗內存的元兇。
4.指令ps找出消耗內存的元兇

[root@localhost ~]# ps -A –sort -rss -o comm,pmem,pcpu |uniq -c |head -15
1 COMMAND %MEM %CPU
1 mysqld 0.6 0.0
503 php-cgi 0.3 0.0
5 php-cgi 0.2 0.0
1 php-cgi 0.1 0.0
1 php-cgi 0.0 0.0
1 memcached 0.0 0.0
1 sshd 0.0 0.0
1 nginx 0.0 0.0
1 sshd 0.0 0.0
1 nginx 0.0 0.0
2 bash 0.0 0.0
3 nginx 0.0 0.0
1 sshd 0.0 0.0
1 nginx 0.0 0.0

指令ps比較常用,也比較簡單。上面報告結果,我們一眼就可以命中php-cgi這個進程。雖然單個php-cgi佔用內存並不算太大,但是503個php-cgi進程,就有點恐怖了。幾乎佔盡了全部內存(503*0.3%)。我們可以猜想,php-cgi由php-fpm管理,是不是可以php-fpm的某個參數配置不當,導致打開過多的php-cgi進程。
5. 設置php-fpm進程數量管理
通過重新將php-conf.conf的max_children值設置爲150,系統內存又恢復到正常使用情況。free、si、so、b均表示內存系統資源正常,沒有壓力。

php-cgi進程釋放的內存並不會被系統立即回收,一個php-cgi大概佔用20MB內存(取決於你加載的php extensions)。所以,有必要限制你啓動的php-cgi進程數量。那麼,這個數量多少合適呢,你可以在服務器高峯期通過top統計出php-cgi數量。也可以像php-fpm建議的那樣,通過netstat -np | grep 127.0.0.1:9000來收集數據,通過設置max_children使等待的數量儘量小

6.一個php-cgi佔用多少內存
一個php-cgi進程,大概佔用多少內存呢,大概是20MB(具體的要看你的php加載了多少模塊)。可以通過pmap指令查看哪些地方佔用了內存。所以,儘量不要加載不必要的php擴展模塊,可以減少不必要的內存浪費。

[root@localhost etc]# pmap $(pgrep php-cgi |head -1)
6746: /usr/local/php/bin/php-cgi –fpm –fpm-config /usr/local/php/etc/php-fpm.conf
0000000000400000 6680K r-x– /usr/local/php/bin/php-cgi
0000000000c86000 268K rw— /usr/local/php/bin/php-cgi
0000000000cc9000 56K rw— [ anon ]
0000000005012000 2240K rw— [ anon ]
0000003efd200000 112K r-x– /lib64/ld-2.5.so
…….
00002ac28a7a5000 2048K —– /usr/local/php/lib/php/extensions/no-debug-non-zts-20060613/xhprof.so
00002ac28a9a5000 4K rw— /usr/local/php/lib/php/extensions/no-debug-non-zts-20060613/xhprof.so
00002ac28a9a6000 84K r-x– /usr/local/php/lib/php/extensions/no-debug-non-zts-20060613/apc.so
00002ac28a9bb000 2048K —– /usr/local/php/lib/php/extensions/no-debug-non-zts-20060613/apc.so
00002ac28abbb000 8K rw— /usr/local/php/lib/php/extensions/no-debug-non-zts-20060613/apc.so
00002ac28abbd000 32K rw— [ anon ]
00002ac28abd4000 40K r-x– /lib64/libnss_files-2.5.so
00002ac28abde000 2044K —– /lib64/libnss_files-2.5.so
00002ac28addd000 4K r—- /lib64/libnss_files-2.5.so
00002ac28adde000 4K rw— /lib64/libnss_files-2.5.so
00007fffa717e000 84K rw— [ stack ]
ffffffffff600000 8192K —– [ anon ]
total 154172K

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章