1.1 Linux的php-fpm優化心得-php-fpm進程占用內存大和不釋放內存問題
LNMP架構中PHP是運行在FastCGI模式下,按照官方的說法,php-cgi會在每個請求結束的時候會回收腳本使用的全部內存,但是並不會釋放給操作系統,而是繼續持有以應對下一次PHP請求。而php-fpm是FastCGI進程管理器,用於控制php的內存和進程等。
解決的辦法就是通過php-fpm優化總的進程數和單個進程占用的內存,從而解決php-fpm進程占用內存大和不釋放內存的問題。
1.1.1 分析判斷php-fpm內存使用情況
使用Glances命令,再按下m,就可以查看到當前VPS主機進程內存占用情況了,按照占用內存由多到少排序(或者使用Top命令,按下M,效果是一樣的)。如下圖(點擊放大):
Glances安裝參考:https://www.ibm.com/developerworks/cn/linux/1304_caoyq_glances/index.html
這是一張重啟后進程內存占用情況圖,從前后對比中可以發現:隨着開機時間的增長,php-fpm占用的內存越來越大
查看當前php-fpm總進程數,命令:ps -ylC php-fpm --sort:rss
。其中RSS就是占用的內存情況。如下圖:
查看當前php-fpm進程的內存占用情況及啟動時間,命令如下:
ps -e -o 'pid,comm,args,pcpu,rsz,vsz,stime,user,uid'|grep www|sort -nrk5
注意:www是啟動用戶,根據你自己情況寫過濾條件
從下圖可以看出當前php-fpm所有進程平均每個進程占用了60-70MB的內存,啟動時間,是當天的話就是3:12,否則會顯示是X月X日。
查看當前php-fpm進程平均占用內存情況,一般來說一個php-fpm進程占用的內存為30-40MB,本次查詢的結果是60MB,顯然是多了。命令如下:
ps --no-headers -o "rss,cmd" -C php-fpm | awk '{ sum+=$1 } END { printf ("%d%s\n", sum/NR/1024,"M") }' 結果61M
1.2 熟悉php-fpm配置文件說明
php-fpm.conf就是php-fpm的配置文件,路徑一般在:/etc/php-fpm.conf,如下圖:
php-fpm.conf幾個重要的參數說明如下:
pm = dynamic #指定進程管理方式,有3種可供選擇:static、dynamic和ondemand。 pm.max_children = 16 #static模式下創建的子進程數或dynamic模式下同一時刻允許最大的php-fpm子進程數量。 pm.start_servers = 10 #動態方式下的起始php-fpm進程數量。 pm.min_spare_servers = 8 #動態方式下服務器空閑時最小php-fpm進程數量。 pm.max_spare_servers = 16 #動態方式下服務器空閑時最大php-fpm進程數量。 pm.max_requests = 2000 #php-fpm子進程能處理的最大請求數。 pm.process_idle_timeout = 10s request_terminate_timeout = 120
pm三種進程管理模式說明如下:
pm = static,始終保持一個固定數量的子進程,這個數由pm.max_children定義,這種方式很不靈活,也通常不是默認的。 pm = dynamic,啟動時會產生固定數量的子進程(由pm.start_servers控制)可以理解成最小子進程數,而最大子進程數則由pm.max_children去控制,子進程數會在最大和最小數范圍中變化。閑置的子進程數還可以由另2個配置控制,分別是pm.min_spare_servers和pm.max_spare_servers。如果閑置的子進程超出了pm.max_spare_servers,則會被殺掉。小於pm.min_spare_servers則會啟動進程(注意,pm.max_spare_servers應小於pm.max_children)。 pm = ondemand,這種模式和pm = dynamic相反,把內存放在第一位,每個閑置進程在持續閑置了pm.process_idle_timeout秒后就會被殺掉,如果服務器長時間沒有請求,就只會有一個php-fpm主進程。弊端是遇到高峰期或者如果pm.process_idle_timeout的值太短的話,容易出現504 Gateway Time-out錯誤,因此pm = dynamic和pm = ondemand誰更適合視實際情況而定。
1.3 解決php-fpm進程占用內存大問題
1.3.1 調整管理模式
static管理模式適合比較大內存的服務器,而dynamic則適合小內存的服務器,你可以設置一個pm.min_spare_servers和pm.max_spare_servers合理范圍,這樣進程數會不斷變動。ondemand模式則更加適合微小內存,例如512MB或者256MB內存,以及對可用性要求不高的環境。
1.3.2 減少php-fpm進程數
如果你的主機的內存被占用耗盡,可以檢查一下你的php-fpm進程數,按照php-fpm進程數=內存/2/30來計算,1GB內存適合的php-fpm進程數為10-20之間,具體還得根據你的PHP加載的附加組件有關系。
1.3.3 php-fpm配置實例
這里以1GB內存的VPS配置php-fpm為演示,實際操作來看設置數值還得根據服務器本身的性能、PHP等綜合考慮。
pm = dynamic #dynamic和ondemand適合小內存。 pm.max_children = 15 #static模式下生效,dynamic不生效。 pm.start_servers = 8 #dynamic模式下開機的進程數量。 pm.min_spare_servers = 6 #dynamic模式下最小php-fpm進程數量。 pm.max_spare_servers = 15 #dynamic模式下最大php-fpm進程數量。
1.4 解決php-fpm進程不釋放內存問題
上面通過減少php-fpm進程總數來達到減少php-fpm內存占用的問題,實際使用過程中發現php-fpm進程還存長期占用內存而不釋放的問題。解決的方法就是減少pm.max_requests數
最大請求數max_requests,即當一個 PHP-CGI 進程處理的請求數累積到 max_requests 個后,自動重啟該進程,這樣達到了釋放內存的目的了。以1GB內存的VPS主機設置為例(如果你設置的數值沒有達到釋放內存可以繼續調低):
pm.max_requests = 500
當php-fpm進程達到了pm.max_requests設定的數值后,就會重啟該進程,從而釋放內存。下圖是我測試后的效果,可以看出php-fpm進程被強制結束並釋放了內存。
1.5 總結
對於大內存以及對並發和可用性要求的話,建議使用static管理模式+最大的pm.max_children。如果是小內存的服務器,建議使用dynamic或者ondemand模式,同時降低pm.start_servers和pm.max_spare_servers進程數。
為什么我調整了參數沒有達到應有的效果?根據wzfou.com的經驗,php-fpm配置文件參數不能一概而論,必須要結合服務器自身的性能、WEB動態內容以及對可用性的要求來進行調整,內存長期占用最好是再檢查一下是否有內存泄露。
文章出自:挖站否 https://wzfou.com/php-fpm/