1. 程式人生 > >nginx系統占用CPU過高

nginx系統占用CPU過高

阿裏 cpu高 pid 就是 tin nginx ret bject gin

一般來說,只要您的linux系統出現占用CPU資源高,或者占用內存多的放,都離不開php-cgi或php-fpm進程,當然,還有一個進程就是mysqld進程,遇到這樣的問題,如果對linux系統不是很熟悉的話,是相當頭痛的

在此環境下,一般php-cgi運行是非常穩定的,但也遇到過php-cgi占用太多cpu資源而導致服務器響應過慢,我所遇到的php-cgi進程占用cpu資源過多的主要原因有如下幾個:

可能存在的原因1:
1、一些php的擴展與php版本兼容存在問題,實踐證明 eAccelerater與某些php版本兼容存在問題,具體表現時啟動php-cgi進程後,運行10多分鐘,奇慢無比,但靜態資源訪問很快,服務器負載也很正常(說明nginx沒有問題,而是php-cgi進程的問題),解決辦法就是從php.ini中禁止掉eAccelerater模塊,再重啟php-cgi進程即可.這一個一般來說是比如好解決的.

eAccelerator 組件不知什麽原因占用 CPU 過高,打開 php.ini
vi /usr/local/php/etc/php.ini
刪除 eAccelerator 的配置信息,重啟 lnmp
/root/lnmp restart
但還是沒有徹底解決問題,幾個小時後,我又重啟了 lnmp ,居然發現,似乎已經越來越平穩啦。
可能用到的命令:

top //查看CPU、內存使用信息,查看哪個進程占用CPU高以及它的PID
ll /proc/PID號/fd/ // 通過PID找到哪個文件操作的進程,進而知道問題所在
https://www.jb51.net/article/92978.htm

可能存在的原因2:
參數配置不當

php-fpm優化方法
php-fpm存在兩種方式,一種是直接開啟指定數量的php-fpm進程,不再增加或者減少;
另一種則是開始時開啟一定數量的php-fpm進程,當請求量變大時,動態的增加php-fpm進程數到上限,當空閑時自動釋放空閑的進程數到一個下限。
這兩種不同的執行方式,可以根據服務器的實際需求來進行調整。

要用到的一些參數,分別是pm、pm.max_children、pm.start_servers、pm.min_spare_servers和pm.max_spare_servers。

pm表示使用那種方式,有兩個值可以選擇,就是static(靜態)或者dynamic(動態)。

下面4個參數的意思分別為:

pm.max_children:靜態方式下開啟的php-fpm進程數量,在動態方式下他限定php-fpm的最大進程數(這裏要註意pm.max_spare_servers的值只能小於等於pm.max_children)
pm.start_servers:動態方式下的起始php-fpm進程數量。
pm.min_spare_servers:動態方式空閑狀態下的最小php-fpm進程數量。
pm.max_spare_servers:動態方式空閑狀態下的最大php-fpm進程數量。
如果dm設置為static,那麽其實只有pm.max_children這個參數生效。系統會開啟設置的數量個php-fpm進程。

如果dm設置為dynamic,4個參數都生效。系統會在php-fpm運行開始時啟動pm.start_servers個php-fpm進程,然後根據系統的需求動態在pm.min_spare_servers和pm.max_spare_servers之間調整php-fpm進程數。

那麽,對於服務器,選擇哪種執行方式比較好呢?事實上,跟Apache一樣,運行的PHP程序在執行完成後,或多或少會有內存泄露的問題。這也是為什麽開始時一個php-fpm進程只占用3M左右內存,運行一段時間後就會上升到20-30M的原因了。(www. 腳本學堂)

所以,動態方式因為會結束掉多余的進程,可以回收釋放一些內存,所以推薦在內存較少的服務器或者VPS上使用。具體最大數量根據 內存/20M 得到。
比如說512M的VPS,建議pm.max_spare_servers設置為20(512*0.8/20)。至於pm.min_spare_servers,則建議根據服務器的負載情況來設置,比較合適的值在5~10之間。

然後對於比較大內存的服務器來說,設置為靜態的話會提高效率。
因為頻繁開關php-fpm進程也會有時滯,所以內存夠大的情況下開靜態效果會更好。數量也可以根據 內存/30M 得到。
比如說2GB內存的服務器,可以設置為50;4GB內存可以設置為100等。

對於內存大的服務器(比如8G以上)來說,指定靜態的max_children實際上更為妥當,因為這樣不需要進行額外的進程數目控制,會提高效率。因為頻繁開關php-fpm進程也會有時滯,所以內存夠大的情況下開靜態效果會更好。數量也可以根據 內存/30M 得到,比如8GB內存可以設置為100,那麽php-fpm耗費的內存就能控制在 2G-3G的樣子。如果內存稍微小點,比如1G,那麽指定靜態的進程數量更加有利於服務器的穩定。這樣可以保證php-fpm只獲取夠用的內存,將不多的內存分配給其他應用去使用,會使系統的運行更加暢通。
對於小內存的服務器來說,比如256M內存的VPS,即使按照一個20M的內存量來算,10個php-cgi進程就將耗掉200M內存,那系統的崩潰就應該很正常了。因此應該盡量地控制php-fpm進程的數量,大體明確其他應用占用的內存後,給它指定一個靜態的小數量,會讓系統更加平穩一些。或者使用動態方式,因為動態方式會結束掉多余的進程,可以回收釋放一些內存,所以推薦在內存較少的服務器或VPS上使用。具體最大數量根據 內存/20M 得到。比如說512M的VPS,建議pm.max_spare_servers設置為20。至於pm.min_spare_servers,則建議根據服務器的負載情況來設置,比較合適的值在5~10之間。
https://www.jb51.net/article/92982.htm

比如,如果是512M的vps,設置的參數如下:

代碼示例:
pm=dynamic
pm.max_children=20
pm.start_servers=5
pm.min_spare_servers=5
pm.max_spare_servers=20
可以最大的節省內存並提高執行效率。

PS.
pm.min_spare_servers、pm.max_spare_servers這2個參數一開始我以為是指空閑進程,但是後來服務器給我報了一個錯誤:
pm.start_servers(70) must not be less than pm.min_spare_servers(15) and not greater than pm.max_spare_servers(60)
要求pm.start_servers的值在pm.min_spare_servers和pm.max_spare_servers之間,經過測試,得出上述結論。
http://blog.itpub.net/14184018/viewspace-1797411/
https://blog.csdn.net/wangschang/article/details/38540617

可能存在的原因3:

  1. 程序中可能存在死循環,導致服務器負載超高(使用top指令查看負載高達100+), 需要借助Linux的proc虛擬文件系統找到具體的問題程序

可能存在的原因4:

  1. php程序不合理使用session, 這個發生在開源微博記事狗程序上,具體表現是有少量php-cgi進程(不超過10個)的cpu使用率達98%以上, 服務器負載在4-8之間,這個問題的解決,仍然需要借助Linux的proc文件系統找出原因.

可能存在的原因5:

  1. 程序中存在過度耗時且不可能完成的操作(還是程序的問題),例如discuz x 1.5的附件下載功能:

source/module/forum/forum_attachement.php中的定義

function getremotefile($file) {
global $_G;@set_time_limit(0);
br/>@set_time_limit(0);
$ftp = ftpcmd(‘object‘);
$tmpfile = @tempnam($_G[‘setting‘][‘attachdir‘], ‘‘);
if($ftp->ftp_get($tmpfile, ‘forum/‘.$file, FTP_BINARY)) {@readfile($tmpfile);
br/>@readfile($tmpfile);
} else {@unlink($tmpfile);
br/>@unlink($tmpfile);
}
}
return TRUE;
}
沒有對傳入的參數作任何初步檢查,而且設置了永不超時,並且使用readfile一次讀取超大文件,就可能存在以下問題:

1.. 以http方式讀取遠程附件過度耗時

  1. FTP無法連接時,如何及時反饋出錯誤?

  2. readfile是一次性讀取文件加載到內存中並輸出,當文件過大時,內存消耗驚人

根據實驗發現采用readfile一次性讀取,內存消耗會明顯增加,但是CPU的利用率會下降較多。如果采用分段讀取的方式,內存消耗會稍微下降,而CPU占用卻會明顯上升.

對discuz x 1.5的這個bug較好解決方法就是後臺重新正確設置遠程附件參數.

以下是我逐步整理的故障排除步驟:

  1. 得到占用cpu資源過多的php-cgi進程的pid(進程id), 使用top命令即可,如下圖:

top命令

經過上圖,可以發現,有兩個php-cgi進程的cpu資源占用率過高,pid分別是10059,11570,這一般都是程序優化不夠造成,如何定位問題的php程序位置?

  1. 找出占內存高的進程所使用的文件

/proc/文件系統保存在內存中,主要保存系統的狀態,關鍵配置等等,而/proc/目錄下有很多數字目錄,就是進程的相關信息,如下圖,我們看看進程10059正在使用哪些文件?

找出進程所使用的文件

補充一下,下面的這個命令,在查找原因是用得非常多,而且我們一般情況下,可以多試下這個命令.

ll /proc/pid/fd/
顯然,使用了/home/tmp/sess_*文件,這明顯是PHP的session文件, 我們查看這個session文件的內容為:view_time|123333312412

到這裏,我們已經可以懷疑是由於php程序寫入一個叫view_time的session項而引起, 那麽剩余的事件就是檢查包含view_time的所有php文件,然後修改之(比如改用COOKIE),這實話, 這個view_time並非敏感數據,僅僅記錄用戶最後訪問時間,實在沒必要使用代價巨大的session, 而應該使用cookie.

  1. 找出有問題的程序,修改之

使用vi編輯以下shell程序(假設網站程序位於/www目錄下)

#!/bin/bash
find /www/ -name "*.php" > list.txt
f=cat ./list.txt
for n in $f
do
r=egrep ‘view_time‘ $n
if [ ! "$r" = "" ] ; then
echo $n
fi
done
運行這個shell程序,將輸出包含有view_time的文件, 對記事狗微博系統,產生的問題位於modules/topic.mod.class文件中.

接下來就是處理這個文件了.

在免費部落的網站中,與linux下占用cpu,內存資源高相關的話題還有:

1.wordpress使用lnmp環境cpu占用高到100%的處理

2.LNMP Nginx環境下CPU某個時間段占用高的處理

3.阿裏雲VPS下LNMP cpu 100% mysqld和php-fpm占內存的解決方法

小結

php-fpm目前主要又兩個分支,分別對應於php-5.2.x的版本和php-5.3.x的版本。在5.2.x的版本中,php-fpm.conf使用的是xml格式,而在新的5.3.x版本中,則是和php.ini一樣的配置風格。
在5.2.x版本中,php-fpm.conf中對於進程管理號稱是有兩種風格,一種是靜態(static)的,一種是類似於apache風格(apache-like)的。

參考地址:
http://www.mfbuluo.com/23122.html

nginx系統占用CPU過高